Formatting

This commit is contained in:
2026-06-01 12:36:55 +02:00
parent b30243f674
commit c7e1d69e2d
37 changed files with 2187 additions and 1925 deletions
+17 -6
View File
@@ -100,8 +100,12 @@ export class AppService extends EventEmitter<AppEventMap> {
const templates = await engine.listImportedTemplates();
templates.forEach(async (template) => {
engine.updateUnspentOutputsForTemplate(generateTemplateIdentifier(template));
engine.subscribeToScriptHashForTemplate(generateTemplateIdentifier(template));
engine.updateUnspentOutputsForTemplate(
generateTemplateIdentifier(template),
);
engine.subscribeToScriptHashForTemplate(
generateTemplateIdentifier(template),
);
});
};
@@ -127,7 +131,14 @@ export class AppService extends EventEmitter<AppEventMap> {
});
const rates = await RatesService.create(settings);
return new AppService(engine, walletStorage, config, electrum, rates, settings);
return new AppService(
engine,
walletStorage,
config,
electrum,
rates,
settings,
);
}
constructor(
@@ -298,9 +309,9 @@ export class AppService extends EventEmitter<AppEventMap> {
async start(): Promise<void> {
// Start rates in the background so BCH -> fiat conversions become reactive in the TUI.
this.rates.start().catch((err) =>
console.error('Error starting rates service:', err),
);
this.rates
.start()
.catch((err) => console.error("Error starting rates service:", err));
// Get the invitations db
const invitationsDb = this.storage.child("invitations");
+134 -44
View File
@@ -80,7 +80,7 @@ interface WalletMetadataIndex {
* I've tried to fundamental approaches so far:
* - UTXO first
* - Invitation first
*
*
* The issue is that neither of these end up being simple or effective
* UTXO first makes tracking utxos across invitations extremely difficult. So if you receive a UTXO from an invitation and then spend it on another, you wont even see that old invitation.
* Invitation first makes fitting UTXOs that dont have an invitation (say if someone sent directly to your address) extremely difficult. You end up having to run a UTXO first pass anyway, and then end up with conflicts around resolved roles.
@@ -95,7 +95,6 @@ export class HistoryService {
private invitations: Invitation[],
) {}
/**
* I Might swap this over to invitation based history before the event to make it a bit more evident... Really not happy with the UTXO for demo purposes
* But for the actual usage, UTXO is easier to follow - just not good for demo
@@ -114,7 +113,10 @@ export class HistoryService {
for (const context of utxoContexts) {
const invitationIdentifier = context.utxo.reservedBy;
if (invitationIdentifier && invitationContexts.has(invitationIdentifier)) {
if (
invitationIdentifier &&
invitationContexts.has(invitationIdentifier)
) {
const group = reservedUtxosByInvitation.get(invitationIdentifier) ?? [];
group.push(context);
reservedUtxosByInvitation.set(invitationIdentifier, group);
@@ -141,13 +143,15 @@ export class HistoryService {
});
}
private async buildInvitationContextIndex(): Promise<Map<string, InvitationContext>> {
private async buildInvitationContextIndex(): Promise<
Map<string, InvitationContext>
> {
const contexts = new Map<string, InvitationContext>();
for (const invitation of this.invitations) {
const templateIdentifier = invitation.data.templateIdentifier;
const template = templateIdentifier
? (await this.engine.getTemplate(templateIdentifier)) ?? null
? ((await this.engine.getTemplate(templateIdentifier)) ?? null)
: null;
contexts.set(invitation.data.invitationIdentifier, {
invitation,
@@ -181,9 +185,13 @@ export class HistoryService {
}
for (const templateIdentifier of templateIdentifiers) {
const scriptHashDataList = await this.engine.listScriptHashesForTemplate(templateIdentifier);
const scriptHashDataList =
await this.engine.listScriptHashesForTemplate(templateIdentifier);
for (const scriptHashData of scriptHashDataList) {
scriptHashDataByScriptHash.set(scriptHashData.scriptHash, scriptHashData);
scriptHashDataByScriptHash.set(
scriptHashData.scriptHash,
scriptHashData,
);
}
}
@@ -194,10 +202,12 @@ export class HistoryService {
utxo: UnspentOutputData,
metadataIndex: WalletMetadataIndex,
): Promise<UtxoContext> {
const scriptHashData = metadataIndex.scriptHashDataByScriptHash.get(utxo.scriptHash);
const scriptHashData = metadataIndex.scriptHashDataByScriptHash.get(
utxo.scriptHash,
);
const templateIdentifier = scriptHashData?.templateIdentifier;
const template = templateIdentifier
? (await this.engine.getTemplate(templateIdentifier)) ?? null
? ((await this.engine.getTemplate(templateIdentifier)) ?? null)
: null;
return {
@@ -213,8 +223,15 @@ export class HistoryService {
): WalletHistoryItem {
const invitation = context.invitation.data;
const entityRoles = this.deriveInvitationEntityRoles(context);
const inputs = this.projectInvitationInputs(context, reservedContexts, entityRoles);
const inputUtxoIds = this.listInvitationInputUtxoIds(context, reservedContexts);
const inputs = this.projectInvitationInputs(
context,
reservedContexts,
entityRoles,
);
const inputUtxoIds = this.listInvitationInputUtxoIds(
context,
reservedContexts,
);
const outputs = this.projectInvitationOutputs(
context,
reservedContexts,
@@ -263,7 +280,9 @@ export class HistoryService {
const outpointIndex = input.outpointIndex;
if (txid === undefined || outpointIndex === undefined) continue;
const utxoContext = reservedByOutpoint.get(this.getOutpointKey(txid, outpointIndex));
const utxoContext = reservedByOutpoint.get(
this.getOutpointKey(txid, outpointIndex),
);
// TODO: Remove this reservation-based filter once Engine/library cleanup releases stale invitation reservations internally.
if (!utxoContext) continue;
@@ -309,15 +328,20 @@ export class HistoryService {
// UTXO-first: committed outputs only matter here if they resolve to a wallet UTXO currently reserved by this invitation.
if (!matchingContext) continue;
const lockingBytecode = this.getOutputLockingBytecodeHex(output) ?? matchingContext.scriptHashData?.lockingBytecode;
const outputIdentifier = output.outputIdentifier ?? matchingContext.scriptHashData?.outputIdentifier;
const lockingBytecode =
this.getOutputLockingBytecodeHex(output) ??
matchingContext.scriptHashData?.lockingBytecode;
const outputIdentifier =
output.outputIdentifier ??
matchingContext.scriptHashData?.outputIdentifier;
const role =
output.roleIdentifier ??
this.getFirstEntityRole(entityRoles, commit.entityIdentifier) ??
matchingContext.scriptHashData?.roleIdentifier;
const valueSatoshis = output.valueSatoshis !== undefined
? BigInt(output.valueSatoshis)
: BigInt(matchingContext.utxo.valueSatoshis);
const valueSatoshis =
output.valueSatoshis !== undefined
? BigInt(output.valueSatoshis)
: BigInt(matchingContext.utxo.valueSatoshis);
usedUtxoIds.add(this.getUtxoId(matchingContext.utxo));
@@ -369,8 +393,11 @@ export class HistoryService {
const outpointIndex = input.outpointIndex;
if (txid === undefined || outpointIndex === undefined) continue;
const utxoContext = reservedByOutpoint.get(this.getOutpointKey(txid, outpointIndex));
if (utxoContext) invitationInputUtxoIds.add(this.getUtxoId(utxoContext.utxo));
const utxoContext = reservedByOutpoint.get(
this.getOutpointKey(txid, outpointIndex),
);
if (utxoContext)
invitationInputUtxoIds.add(this.getUtxoId(utxoContext.utxo));
}
}
@@ -390,9 +417,17 @@ export class HistoryService {
return reservedContexts.find((context) => {
if (usedUtxoIds.has(this.getUtxoId(context.utxo))) return false;
if (scriptHash && context.utxo.scriptHash === scriptHash) return true;
if (lockingBytecode && context.scriptHashData?.lockingBytecode === lockingBytecode) return true;
if (
lockingBytecode &&
context.scriptHashData?.lockingBytecode === lockingBytecode
)
return true;
if (output.outputIdentifier && context.scriptHashData?.outputIdentifier === output.outputIdentifier) return true;
if (
output.outputIdentifier &&
context.scriptHashData?.outputIdentifier === output.outputIdentifier
)
return true;
return false;
});
}
@@ -423,7 +458,11 @@ export class HistoryService {
id: this.getUtxoId(context.utxo),
outputIdentifier,
role,
description: this.describeOutputFromTemplate(outputIdentifier, context.template, {}),
description: this.describeOutputFromTemplate(
outputIdentifier,
context.template,
{},
),
valueSatoshis: BigInt(context.utxo.valueSatoshis),
outpoint: {
txid: context.utxo.outpointTransactionHash,
@@ -435,17 +474,22 @@ export class HistoryService {
};
}
private deriveInvitationEntityRoles(context: InvitationContext): Map<string, string[]> {
private deriveInvitationEntityRoles(
context: InvitationContext,
): Map<string, string[]> {
const invitation = context.invitation.data;
const rolesByEntity = new Map<string, Set<string>>();
const allEntities = new Set(invitation.commits.map((commit) => commit.entityIdentifier));
const allEntities = new Set(
invitation.commits.map((commit) => commit.entityIdentifier),
);
for (const entityIdentifier of allEntities) {
rolesByEntity.set(entityIdentifier, new Set());
}
for (const commit of invitation.commits) {
const roles = rolesByEntity.get(commit.entityIdentifier) ?? new Set<string>();
const roles =
rolesByEntity.get(commit.entityIdentifier) ?? new Set<string>();
for (const input of commit.data.inputs ?? []) {
if (input.roleIdentifier) roles.add(input.roleIdentifier);
}
@@ -459,9 +503,10 @@ export class HistoryService {
}
const action = context.template?.actions?.[invitation.actionIdentifier];
const participantRoles = action?.requirements?.participants
?.map((participant) => participant.role)
.filter((role): role is string => typeof role === "string") ?? [];
const participantRoles =
action?.requirements?.participants
?.map((participant) => participant.role)
.filter((role): role is string => typeof role === "string") ?? [];
const explicitlyFilledRoles = new Set<string>();
for (const roles of rolesByEntity.values()) {
for (const role of roles) explicitlyFilledRoles.add(role);
@@ -473,7 +518,10 @@ export class HistoryService {
.filter(([, roles]) => roles.size === 0)
.map(([entityIdentifier]) => entityIdentifier);
if (unfilledParticipantRoles.length === 1 && entitiesWithoutRoles.length >= 1) {
if (
unfilledParticipantRoles.length === 1 &&
entitiesWithoutRoles.length >= 1
) {
const inferredRole = unfilledParticipantRoles[0];
if (inferredRole !== undefined) {
for (const entityIdentifier of entitiesWithoutRoles) {
@@ -517,12 +565,21 @@ export class HistoryService {
inputs: WalletHistoryInput[],
outputs: WalletHistoryOutput[],
): bigint {
const inputTotal = inputs.reduce((total, input) => total + (input.valueSatoshis ?? 0n), 0n);
const outputTotal = outputs.reduce((total, output) => total + (output.valueSatoshis ?? 0n), 0n);
const inputTotal = inputs.reduce(
(total, input) => total + (input.valueSatoshis ?? 0n),
0n,
);
const outputTotal = outputs.reduce(
(total, output) => total + (output.valueSatoshis ?? 0n),
0n,
);
return inputTotal + outputTotal;
}
private describeInvitation(context: InvitationContext, role?: string): string {
private describeInvitation(
context: InvitationContext,
role?: string,
): string {
const invitation = context.invitation.data;
const template = context.template;
if (!template) return invitation.actionIdentifier;
@@ -544,14 +601,27 @@ export class HistoryService {
return this.compileDescription(descriptionTemplate, context.variables);
}
private describeInput(inputIdentifier: string | undefined, context: InvitationContext): string {
private describeInput(
inputIdentifier: string | undefined,
context: InvitationContext,
): string {
if (!inputIdentifier) return "Input";
const input = context.template?.inputs?.[inputIdentifier];
return this.compileDescription(input?.description ?? input?.name ?? inputIdentifier, context.variables);
return this.compileDescription(
input?.description ?? input?.name ?? inputIdentifier,
context.variables,
);
}
private describeOutput(outputIdentifier: string | undefined, context: InvitationContext): string {
return this.describeOutputFromTemplate(outputIdentifier, context.template, context.variables);
private describeOutput(
outputIdentifier: string | undefined,
context: InvitationContext,
): string {
return this.describeOutputFromTemplate(
outputIdentifier,
context.template,
context.variables,
);
}
private describeOutputFromTemplate(
@@ -561,7 +631,10 @@ export class HistoryService {
): string {
if (!outputIdentifier) return "Output";
const output = template?.outputs?.[outputIdentifier];
return this.compileDescription(output?.description ?? output?.name ?? outputIdentifier, variables);
return this.compileDescription(
output?.description ?? output?.name ?? outputIdentifier,
variables,
);
}
private compileDescription(
@@ -569,16 +642,25 @@ export class HistoryService {
variables: Record<string, XOInvitationVariableValue>,
): string {
try {
return compileCashAssemblyString({ cashAssemblyText: description, variables, evaluationDecodeMode: 'utf8' });
return compileCashAssemblyString({
cashAssemblyText: description,
variables,
evaluationDecodeMode: "utf8",
});
} catch {
return this.interpolateSimpleCashAssemblyVariables(description, variables);
return this.interpolateSimpleCashAssemblyVariables(
description,
variables,
);
}
}
private extractInvitationVariables(
invitation: XOInvitation,
): Record<string, XOInvitationVariableValue> {
const committedVariables = invitation.commits.flatMap((c) => c.data.variables ?? []);
const committedVariables = invitation.commits.flatMap(
(c) => c.data.variables ?? [],
);
return committedVariables.reduce(
(acc, variable) => {
if (!variable.variableIdentifier) return acc;
@@ -596,15 +678,21 @@ export class HistoryService {
: String(input.outpointTransactionHash);
}
private getOutputLockingBytecodeHex(output: XOInvitationOutput): string | undefined {
private getOutputLockingBytecodeHex(
output: XOInvitationOutput,
): string | undefined {
if (output.lockingBytecode === undefined) return undefined;
return typeof output.lockingBytecode === "string"
? output.lockingBytecode
: binToHex(output.lockingBytecode);
}
private async getScriptHashData(scriptHash: string): Promise<ScriptHashData | undefined> {
return (this.engine as unknown as { state: State }).state.getScriptHashData(scriptHash);
private async getScriptHashData(
scriptHash: string,
): Promise<ScriptHashData | undefined> {
return (this.engine as unknown as { state: State }).state.getScriptHashData(
scriptHash,
);
}
private getOutpointKey(txid: string, index: number): string {
@@ -627,7 +715,9 @@ export class HistoryService {
return text.replace(
/\$\(<([^>]+)>\)/g,
(match, variableIdentifier: string) => {
if (!Object.prototype.hasOwnProperty.call(variables, variableIdentifier)) {
if (
!Object.prototype.hasOwnProperty.call(variables, variableIdentifier)
) {
return match;
}
return String(variables[variableIdentifier]);
+64 -30
View File
@@ -3,7 +3,13 @@ import type {
Engine,
GetSpendableResourcesParameters,
} from "@xo-cash/engine";
import { generateTemplateIdentifier, hasInvitationExpired, mergeInvitationCommits, serializeInvitation, deserializeInvitation } from "@xo-cash/engine";
import {
generateTemplateIdentifier,
hasInvitationExpired,
mergeInvitationCommits,
serializeInvitation,
deserializeInvitation,
} from "@xo-cash/engine";
import type {
XOInvitation,
XOInvitationCommit,
@@ -92,7 +98,9 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
}
// engine invitation (I have no idea if this is required)
const engineInvitation = await dependencies.engine.importInvitation(serializeInvitation(invitation));
const engineInvitation = await dependencies.engine.importInvitation(
serializeInvitation(invitation),
);
// Create the invitation
const invitationInstance = new Invitation(engineInvitation, dependencies);
@@ -287,7 +295,9 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
return payload;
}
private unwrapLegacyInvitationUpdatedPayload(payload: unknown): unknown | null {
private unwrapLegacyInvitationUpdatedPayload(
payload: unknown,
): unknown | null {
if (
payload &&
typeof payload === "object" &&
@@ -308,7 +318,10 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
invitation: XOInvitation = this.data,
): Promise<void> {
this.syncServer.publishInvitation(invitation).catch((error) => {
this.emit("error", error instanceof Error ? error : new Error(String(error)));
this.emit(
"error",
error instanceof Error ? error : new Error(String(error)),
);
});
}
@@ -362,7 +375,9 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
private async computeStatusInternal(): Promise<string> {
let missingReqs;
try {
const missingRequirements = await this.engine.listMissingRequirements(this.data.invitationIdentifier);
const missingRequirements = await this.engine.listMissingRequirements(
this.data.invitationIdentifier,
);
missingReqs = missingRequirements.templateRequirements;
} catch {
return "unknown";
@@ -454,13 +469,18 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
* Update the status of the invitation and emit the new single-word status.
*/
private async updateStatus(): Promise<void> {
this.computeStatus().then(status => {
this.status = status;
this.emit("invitation-status-changed", status);
}).catch((error) => {
this.status = `error (${error instanceof Error ? error.message : String(error)})`;
this.emit("error", error instanceof Error ? error : new Error(String(error)));
});
this.computeStatus()
.then((status) => {
this.status = status;
this.emit("invitation-status-changed", status);
})
.catch((error) => {
this.status = `error (${error instanceof Error ? error.message : String(error)})`;
this.emit(
"error",
error instanceof Error ? error : new Error(String(error)),
);
});
}
/**
@@ -499,7 +519,9 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
*/
async sign(): Promise<void> {
// Sign the invitation
const signedInvitation = await this.engine.signInvitation(this.data.invitationIdentifier);
const signedInvitation = await this.engine.signInvitation(
this.data.invitationIdentifier,
);
// Publish the signed invitation to the sync server
this.publishInvitation(signedInvitation);
@@ -518,9 +540,12 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
* @returns The transaction hash returned by the network after broadcast.
*/
async broadcast(): Promise<string> {
const txHash = await this.engine.executeAction(this.data.invitationIdentifier, {
broadcastTransaction: true,
});
const txHash = await this.engine.executeAction(
this.data.invitationIdentifier,
{
broadcastTransaction: true,
},
);
await this.updateStatus();
@@ -538,7 +563,10 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
await this.ensureAccepted();
// Append the commit to the invitation
this.data = await this.engine.appendInvitation(this.data.invitationIdentifier, data);
this.data = await this.engine.appendInvitation(
this.data.invitationIdentifier,
data,
);
// Sync the invitation to the sync server
await this.publishInvitation(this.data);
@@ -617,8 +645,8 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
const templates = await this.engine.listImportedTemplates();
// For each template, we need to create a 2d array of all the outputs
const outputs = templates.map(template => {
return Object.keys(template.outputs).map(output => {
const outputs = templates.map((template) => {
return Object.keys(template.outputs).map((output) => {
const templateIdentifier = generateTemplateIdentifier(template);
return {
@@ -629,14 +657,18 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
});
// then, for each output, we need to get the spendable resources
const spendableResources = await Promise.all(outputs.flat().map(output => {
return this.engine.getSpendableResources(this.data, {
templateIdentifier: output.templateIdentifier,
outputIdentifier: output.outputIdentifier,
});
}));
const spendableResources = await Promise.all(
outputs.flat().map((output) => {
return this.engine.getSpendableResources(this.data, {
templateIdentifier: output.templateIdentifier,
outputIdentifier: output.outputIdentifier,
});
}),
);
const unspentOutputs = spendableResources.flatMap(resource => resource.unspentOutputs);
const unspentOutputs = spendableResources.flatMap(
(resource) => resource.unspentOutputs,
);
// Update the status of the invitation
await this.updateStatus();
@@ -738,9 +770,11 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
);
// Compile the CashAssembly expression to get the value satoshis (It handles the variable replacement for us)
const valueSatoshis = compileCashAssemblyString(
{ cashAssemblyText: String(valueSatoshisExpression), variables: formattedVariables, evaluationDecodeMode: 'bigint' },
);
const valueSatoshis = compileCashAssemblyString({
cashAssemblyText: String(valueSatoshisExpression),
variables: formattedVariables,
evaluationDecodeMode: "bigint",
});
// Return the value satoshis as a bigint
// TODO: Check this of a vulnerability or crash - I assume there might be one if someone made the `valueSatoshis` a malicious expression
@@ -796,7 +830,7 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
for (const output of outputs) {
if (typeof output === "string") {
const sats = await this.getSatsOut(output);
totalSats += sats
totalSats += sats;
} else {
const sats = await this.getSatsOut(output.output);
totalSats += sats;
+14 -16
View File
@@ -1,16 +1,14 @@
import { OracleClient } from '@generalprotocols/oracle-client';
import { EventEmitter } from '../utils/event-emitter.js';
import {
type RatesEventMap,
} from '../utils/rates/base-rates.js';
import { RatesOracle } from '../utils/rates/rates-oracles.js';
import { SettingsService } from './settings.js';
import { OracleClient } from "@generalprotocols/oracle-client";
import { EventEmitter } from "../utils/event-emitter.js";
import { type RatesEventMap } from "../utils/rates/base-rates.js";
import { RatesOracle } from "../utils/rates/rates-oracles.js";
import { SettingsService } from "./settings.js";
/**
* Event map emitted by {@link RatesService}.
*/
export type RatesServiceEventMap = {
'rate-updated': {
"rate-updated": {
numeratorUnitCode: string;
denominatorUnitCode: string;
price: number;
@@ -39,8 +37,8 @@ export interface RatesAdapter {
listPairs(): Promise<Set<string>>;
formatCurrency(amount: number, targetCurrency: string): string;
on(
type: 'rateUpdated',
listener: (detail: RatesEventMap['rateUpdated']) => void,
type: "rateUpdated",
listener: (detail: RatesEventMap["rateUpdated"]) => void,
): () => void;
}
@@ -96,7 +94,7 @@ export class RatesService extends EventEmitter<RatesServiceEventMap> {
}
this.started = true;
this.unsubscribeFromAdapter = this.adapter.on('rateUpdated', (event) => {
this.unsubscribeFromAdapter = this.adapter.on("rateUpdated", (event) => {
this.handleRateUpdated(event);
});
@@ -145,9 +143,9 @@ export class RatesService extends EventEmitter<RatesServiceEventMap> {
*/
public convertBchToFiat(
satoshis: bigint,
targetCurrency: string = 'USD',
targetCurrency: string = "USD",
): number | null {
const rate = this.getRate(targetCurrency, 'BCH');
const rate = this.getRate(targetCurrency, "BCH");
if (rate === null) {
return null;
}
@@ -161,7 +159,7 @@ export class RatesService extends EventEmitter<RatesServiceEventMap> {
*/
public formatBchToFiat(
satoshis: bigint,
targetCurrency: string = 'USD',
targetCurrency: string = "USD",
): string | null {
const normalizedCurrency = targetCurrency.toUpperCase();
const amount = this.convertBchToFiat(satoshis, normalizedCurrency);
@@ -195,7 +193,7 @@ export class RatesService extends EventEmitter<RatesServiceEventMap> {
/**
* Handles normalized updates from the underlying adapter.
*/
private handleRateUpdated(event: RatesEventMap['rateUpdated']): void {
private handleRateUpdated(event: RatesEventMap["rateUpdated"]): void {
const numeratorUnitCode = event.numeratorUnitCode.toUpperCase();
const denominatorUnitCode = event.denominatorUnitCode.toUpperCase();
const pair = this.getPairKey(numeratorUnitCode, denominatorUnitCode);
@@ -206,7 +204,7 @@ export class RatesService extends EventEmitter<RatesServiceEventMap> {
updatedAt,
});
this.emit('rate-updated', {
this.emit("rate-updated", {
numeratorUnitCode,
denominatorUnitCode,
price: event.price,
+3 -1
View File
@@ -168,7 +168,9 @@ export class SettingsService extends EventEmitter<SettingsServiceEventMap> {
return normalized;
}
const maybeMnemonic = (input as Record<string, unknown>)["default-mnemonic"];
const maybeMnemonic = (input as Record<string, unknown>)[
"default-mnemonic"
];
if (typeof maybeMnemonic === "string" && maybeMnemonic.trim().length > 0) {
normalized["default-mnemonic"] = maybeMnemonic.trim();
}
+1 -1
View File
@@ -142,7 +142,7 @@ export class Storage extends BaseStorage {
*
* This adapter is useful for tests and short-lived sessions where persisted
* SQLite state is not needed.
*
*
* TODO: Move this somewhere else. There is no reason for this to be in the main codebase. We should put this stricly in the tests beacuse that were its actually being used.
* Ideally, we would provide these kind of generic fills as part of our packages somewhere, but these interfaces dont fit our current design.
*/