wallet-core/packages/exchange-backoffice-ui/src/hooks/useOfficer.ts
2023-05-26 16:52:30 -03:00

101 lines
2.3 KiB
TypeScript

import {
AbsoluteTime,
Codec,
buildCodecForObject,
codecForAbsoluteTime,
codecForString,
} from "@gnu-taler/taler-util";
import {
Account,
LockedAccount,
createNewAccount,
unlockAccount,
} from "../account.js";
import {
buildStorageKey,
useLocalStorage,
useMemoryStorage,
} from "@gnu-taler/web-util/browser";
export interface Officer {
account: LockedAccount;
when: AbsoluteTime;
}
const codecForLockedAccount = codecForString() as Codec<LockedAccount>;
export const codecForOfficer = (): Codec<Officer> =>
buildCodecForObject<Officer>()
.property("account", codecForLockedAccount) // FIXME
.property("when", codecForAbsoluteTime) // FIXME
.build("Officer");
export type OfficerState = OfficerNotReady | OfficerReady;
export type OfficerNotReady = OfficerNotFound | OfficerLocked;
interface OfficerNotFound {
state: "not-found";
create: (password: string) => Promise<void>;
}
interface OfficerLocked {
state: "locked";
forget: () => void;
tryUnlock: (password: string) => Promise<void>;
}
interface OfficerReady {
state: "ready";
account: Account;
forget: () => void;
lock: () => void;
}
const OFFICER_KEY = buildStorageKey("officer", codecForOfficer());
const ACCOUNT_KEY = buildStorageKey<Account>("account");
export function useOfficer(): OfficerState {
const accountStorage = useMemoryStorage(ACCOUNT_KEY);
const officerStorage = useLocalStorage(OFFICER_KEY);
const officer = officerStorage.value;
const account = accountStorage.value;
if (officer === undefined) {
return {
state: "not-found",
create: async (pwd: string) => {
const { accountId, safe, signingKey } = await createNewAccount(pwd);
officerStorage.update({
account: safe,
when: AbsoluteTime.now(),
});
accountStorage.update({ accountId, signingKey });
},
};
}
if (account === undefined) {
return {
state: "locked",
forget: () => {
officerStorage.reset();
},
tryUnlock: async (pwd: string) => {
const ac = await unlockAccount(officer.account, pwd);
accountStorage.update(ac);
},
};
}
return {
state: "ready",
account: account,
lock: () => {
accountStorage.reset();
},
forget: () => {
officerStorage.reset();
accountStorage.reset();
},
};
}