v0.5.2-pre.006-fix-010
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: kb-app-demo-desktop/frontend/ts/demo_wallet.ts
|
||||
// version: 4
|
||||
// version: 5
|
||||
|
||||
import * as bootstrap from "bootstrap";
|
||||
import "simplebar";
|
||||
@@ -10,6 +10,8 @@ import { renderJsonViewer } from "./json_viewer.ts";
|
||||
import type { DemoWalletBalancePayload } from "./bindings/kb_app_demo_desktop/demo_wallet/DemoWalletBalancePayload.ts";
|
||||
import type { DemoWalletCreateRequest } from "./bindings/kb_app_demo_desktop/demo_wallet/DemoWalletCreateRequest.ts";
|
||||
import type { DemoWalletExportRequest } from "./bindings/kb_app_demo_desktop/demo_wallet/DemoWalletExportRequest.ts";
|
||||
import type { DemoWalletExecutionProfilePayload } from "./bindings/kb_app_demo_desktop/demo_wallet/DemoWalletExecutionProfilePayload.ts";
|
||||
import type { DemoWalletExecutionSelectionRequest } from "./bindings/kb_app_demo_desktop/demo_wallet/DemoWalletExecutionSelectionRequest.ts";
|
||||
import type { DemoWalletIdentityPayload } from "./bindings/kb_app_demo_desktop/demo_wallet/DemoWalletIdentityPayload.ts";
|
||||
import type { DemoWalletImportRequest } from "./bindings/kb_app_demo_desktop/demo_wallet/DemoWalletImportRequest.ts";
|
||||
import type { DemoWalletInventoryPayload } from "./bindings/kb_app_demo_desktop/demo_wallet/DemoWalletInventoryPayload.ts";
|
||||
@@ -96,6 +98,102 @@ function renderOnchainProfiles(profiles: ReadonlyArray<DemoWalletOnchainProfileP
|
||||
updateOnchainClusterLabel();
|
||||
}
|
||||
|
||||
function selectedExecutionProfilePayload(): DemoWalletExecutionProfilePayload | null {
|
||||
const profile = document.querySelector<HTMLSelectElement>("#walletExecutionProfileSelect")?.value.trim() ?? "";
|
||||
if (!walletInventory || profile.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return walletInventory.execution_profiles.find(candidate => candidate.name === profile) ?? null;
|
||||
}
|
||||
|
||||
function renderExecutionProfiles(profiles: ReadonlyArray<DemoWalletExecutionProfilePayload>): void {
|
||||
const select = document.querySelector<HTMLSelectElement>("#walletExecutionProfileSelect");
|
||||
if (!select) {
|
||||
return;
|
||||
}
|
||||
const previous = select.value;
|
||||
select.replaceChildren();
|
||||
for (const profile of profiles) {
|
||||
const option = document.createElement("option");
|
||||
option.value = profile.name;
|
||||
option.textContent = profile.name;
|
||||
select.appendChild(option);
|
||||
}
|
||||
if (profiles.some(profile => profile.name === previous)) {
|
||||
select.value = previous;
|
||||
} else if (profiles.length > 0) {
|
||||
select.value = profiles[0].name;
|
||||
}
|
||||
}
|
||||
|
||||
function renderExecutionWalletAliases(wallets: ReadonlyArray<DemoWalletIdentityPayload>): void {
|
||||
const select = document.querySelector<HTMLSelectElement>("#walletExecutionAliasSelect");
|
||||
if (!select) {
|
||||
return;
|
||||
}
|
||||
select.replaceChildren();
|
||||
const configuredOption = document.createElement("option");
|
||||
configuredOption.value = "";
|
||||
configuredOption.textContent = "Utiliser la configuration du profil";
|
||||
select.appendChild(configuredOption);
|
||||
for (const wallet of wallets) {
|
||||
const option = document.createElement("option");
|
||||
option.value = wallet.alias;
|
||||
option.textContent = `${wallet.alias} — ${wallet.public_key}`;
|
||||
select.appendChild(option);
|
||||
}
|
||||
}
|
||||
|
||||
function updateExecutionSelectionDisplay(): void {
|
||||
const profile = selectedExecutionProfilePayload();
|
||||
const aliasSelect = document.querySelector<HTMLSelectElement>("#walletExecutionAliasSelect");
|
||||
if (!profile) {
|
||||
setText("#walletExecutionConfiguredAlias", "—");
|
||||
setText("#walletExecutionRuntimeAlias", "—");
|
||||
setText("#walletExecutionEffectiveAlias", "temporaire");
|
||||
if (aliasSelect) {
|
||||
aliasSelect.value = "";
|
||||
}
|
||||
return;
|
||||
}
|
||||
setText("#walletExecutionConfiguredAlias", profile.configured_alias ?? "—");
|
||||
setText("#walletExecutionRuntimeAlias", profile.runtime_alias ?? "—");
|
||||
setText("#walletExecutionEffectiveAlias", profile.effective_alias ?? "temporaire");
|
||||
if (aliasSelect) {
|
||||
const requested = profile.runtime_alias ?? "";
|
||||
if (Array.from(aliasSelect.options).some(option => option.value === requested)) {
|
||||
aliasSelect.value = requested;
|
||||
} else {
|
||||
aliasSelect.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function applyExecutionWalletSelection(): Promise<void> {
|
||||
const profile = document.querySelector<HTMLSelectElement>("#walletExecutionProfileSelect")?.value.trim() ?? "";
|
||||
const aliasText = document.querySelector<HTMLSelectElement>("#walletExecutionAliasSelect")?.value.trim() ?? "";
|
||||
if (profile.length === 0) {
|
||||
setText("#walletExecutionSelectionStatus", "Profil Devnet requis");
|
||||
return;
|
||||
}
|
||||
const request: DemoWalletExecutionSelectionRequest = {
|
||||
profile,
|
||||
alias: aliasText.length === 0 ? null : aliasText,
|
||||
};
|
||||
setText("#walletExecutionSelectionStatus", "Validation...");
|
||||
try {
|
||||
const payload = await invoke<DemoWalletInventoryPayload>("demo_wallet_select_execution_wallet", { request });
|
||||
applyWalletInventoryPayload(payload);
|
||||
const effective = payload.execution_profiles.find(candidate => candidate.name === profile)?.effective_alias ?? null;
|
||||
setText("#walletExecutionSelectionStatus", effective ? `Persistant : ${effective}` : "Configuration du profil");
|
||||
frontendDebug("kb-app-demo-desktop.frontend.demo_wallet", `execution wallet selection updated for ${profile}`);
|
||||
} catch (caughtError) {
|
||||
const message = caughtError instanceof Error ? caughtError.message : String(caughtError);
|
||||
setText("#walletExecutionSelectionStatus", `Erreur : ${message}`);
|
||||
frontendError("kb-app-demo-desktop.frontend.demo_wallet", `Execution wallet selection failed: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function executeWalletRpc(profile: string, method: string, params: unknown[]): Promise<DemoWalletRpcExecutionPayload> {
|
||||
const request: DemoWalletRpcRequest = {
|
||||
profile,
|
||||
@@ -159,6 +257,28 @@ function selectedTransferFormat(selector: string): string {
|
||||
return document.querySelector<HTMLSelectElement>(selector)?.value.trim() ?? "";
|
||||
}
|
||||
|
||||
function selectedExportFormatPayload(): DemoWalletTransferFormatPayload | null {
|
||||
const code = selectedTransferFormat("#walletExportFormatSelect");
|
||||
if (!walletInventory || code.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return walletInventory.transfer_formats.find(format => format.code === code) ?? null;
|
||||
}
|
||||
|
||||
function updateExportFileName(force: boolean): void {
|
||||
const input = document.querySelector<HTMLInputElement>("#walletExportFileNameInput");
|
||||
const alias = document.querySelector<HTMLSelectElement>("#walletExportAliasSelect")?.value.trim() ?? "";
|
||||
const format = selectedExportFormatPayload();
|
||||
if (!input || alias.length === 0 || !format) {
|
||||
return;
|
||||
}
|
||||
const generated = `${alias}.${format.default_extension}`;
|
||||
if (force || input.value.trim().length === 0 || input.dataset.autoGenerated === "true") {
|
||||
input.value = generated;
|
||||
input.dataset.autoGenerated = "true";
|
||||
}
|
||||
}
|
||||
|
||||
function setTransferPublicKey(publicKey: string): void {
|
||||
inspectedTransferPublicKey = publicKey;
|
||||
setText("#walletTransferPublicKey", publicKey.length > 0 ? publicKey : "—");
|
||||
@@ -196,7 +316,8 @@ function renderWalletRows(wallets: ReadonlyArray<DemoWalletIdentityPayload>): vo
|
||||
publicKeyCell.textContent = wallet.public_key;
|
||||
publicKeyCell.className = "font-monospace text-break";
|
||||
formatCell.textContent = `v${wallet.format_version}`;
|
||||
selectedCell.textContent = wallet.selected ? "Oui" : "Non";
|
||||
const executionSelected = selectedExecutionProfilePayload()?.effective_alias === wallet.alias;
|
||||
selectedCell.textContent = executionSelected ? "Oui" : "Non";
|
||||
exploreButton.type = "button";
|
||||
exploreButton.className = "btn btn-sm btn-outline-primary";
|
||||
exploreButton.textContent = "Explorer";
|
||||
@@ -208,7 +329,7 @@ function renderWalletRows(wallets: ReadonlyArray<DemoWalletIdentityPayload>): vo
|
||||
document.querySelector<HTMLElement>("#walletAddressInput")?.scrollIntoView({ behavior: "smooth", block: "center" });
|
||||
});
|
||||
actionCell.appendChild(exploreButton);
|
||||
if (wallet.selected) {
|
||||
if (executionSelected) {
|
||||
row.classList.add("table-primary");
|
||||
}
|
||||
row.append(aliasCell, publicKeyCell, formatCell, selectedCell, actionCell);
|
||||
@@ -216,21 +337,30 @@ function renderWalletRows(wallets: ReadonlyArray<DemoWalletIdentityPayload>): vo
|
||||
}
|
||||
}
|
||||
|
||||
function applyWalletInventoryPayload(payload: DemoWalletInventoryPayload): void {
|
||||
walletInventory = payload;
|
||||
setText("#walletProfile", payload.profile);
|
||||
setText("#walletCluster", payload.cluster);
|
||||
renderOnchainProfiles(payload.onchain_profiles, payload.profile);
|
||||
renderExecutionProfiles(payload.execution_profiles);
|
||||
renderTransferFormats(payload.transfer_formats);
|
||||
renderExportWalletAliases(payload.wallets);
|
||||
renderExecutionWalletAliases(payload.wallets);
|
||||
setText("#walletCreateSecretStatus", payload.create_password_configured ? "configuré" : "absent");
|
||||
setText("#walletSelectedAlias", payload.selected_alias ?? "—");
|
||||
setText("#walletInventoryCount", String(payload.wallets.length));
|
||||
setText("#walletExportDirectory", `${payload.export_directory}/`);
|
||||
setText("#walletInventoryStatus", "OK");
|
||||
renderWalletRows(payload.wallets);
|
||||
updateExecutionSelectionDisplay();
|
||||
updateExportFileName(false);
|
||||
}
|
||||
|
||||
async function refreshWalletInventory(): Promise<void> {
|
||||
setText("#walletInventoryStatus", "Chargement...");
|
||||
try {
|
||||
const payload = await invoke<DemoWalletInventoryPayload>("demo_wallet_inventory");
|
||||
walletInventory = payload;
|
||||
setText("#walletProfile", payload.profile);
|
||||
setText("#walletCluster", payload.cluster);
|
||||
renderOnchainProfiles(payload.onchain_profiles, payload.profile);
|
||||
renderTransferFormats(payload.transfer_formats);
|
||||
renderExportWalletAliases(payload.wallets);
|
||||
setText("#walletCreateSecretStatus", payload.create_password_configured ? "configuré" : "absent");
|
||||
setText("#walletSelectedAlias", payload.selected_alias ?? "—");
|
||||
setText("#walletInventoryCount", String(payload.wallets.length));
|
||||
setText("#walletInventoryStatus", "OK");
|
||||
renderWalletRows(payload.wallets);
|
||||
applyWalletInventoryPayload(payload);
|
||||
frontendDebug("kb-app-demo-desktop.frontend.demo_wallet", "wallet inventory refreshed");
|
||||
} catch (caughtError) {
|
||||
const message = caughtError instanceof Error ? caughtError.message : String(caughtError);
|
||||
@@ -238,6 +368,7 @@ async function refreshWalletInventory(): Promise<void> {
|
||||
setText("#walletInventoryCount", "0");
|
||||
renderWalletRows([]);
|
||||
renderExportWalletAliases([]);
|
||||
renderExecutionWalletAliases([]);
|
||||
frontendError("kb-app-demo-desktop.frontend.demo_wallet", `Wallet inventory loading failed: ${message}`);
|
||||
}
|
||||
}
|
||||
@@ -324,16 +455,16 @@ async function importTransferFile(): Promise<void> {
|
||||
async function exportWallet(): Promise<void> {
|
||||
const alias = document.querySelector<HTMLSelectElement>("#walletExportAliasSelect")?.value.trim() ?? "";
|
||||
const format = selectedTransferFormat("#walletExportFormatSelect");
|
||||
const destinationPath = inputValue("#walletExportDestinationPathInput");
|
||||
if (alias.length === 0 || format.length === 0 || destinationPath.length === 0) {
|
||||
setText("#walletExportStatus", "Wallet, format et destination requis");
|
||||
const fileName = inputValue("#walletExportFileNameInput");
|
||||
if (alias.length === 0 || format.length === 0 || fileName.length === 0) {
|
||||
setText("#walletExportStatus", "Wallet, format et nom de fichier requis");
|
||||
return;
|
||||
}
|
||||
const request: DemoWalletExportRequest = { alias, destination_path: destinationPath, format };
|
||||
const request: DemoWalletExportRequest = { alias, file_name: fileName, format };
|
||||
setText("#walletExportStatus", "Export...");
|
||||
try {
|
||||
await invoke<void>("demo_wallet_export_file", { request });
|
||||
setText("#walletExportStatus", `Exporté : ${alias}`);
|
||||
const exportedPath = await invoke<string>("demo_wallet_export_file", { request });
|
||||
setText("#walletExportStatus", `Exporté : ${exportedPath}`);
|
||||
frontendDebug("kb-app-demo-desktop.frontend.demo_wallet", `native wallet exported: ${alias}`);
|
||||
} catch (caughtError) {
|
||||
const message = caughtError instanceof Error ? caughtError.message : String(caughtError);
|
||||
@@ -647,6 +778,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
document.querySelector<HTMLButtonElement>("#refreshWalletInventoryButton")?.addEventListener("click", () => {
|
||||
void refreshWalletInventory();
|
||||
});
|
||||
document.querySelector<HTMLButtonElement>("#applyWalletExecutionSelectionButton")?.addEventListener("click", () => {
|
||||
void applyExecutionWalletSelection();
|
||||
});
|
||||
document.querySelector<HTMLSelectElement>("#walletExecutionProfileSelect")?.addEventListener("change", () => {
|
||||
updateExecutionSelectionDisplay();
|
||||
if (walletInventory) {
|
||||
renderWalletRows(walletInventory.wallets);
|
||||
}
|
||||
setText("#walletExecutionSelectionStatus", "En attente");
|
||||
});
|
||||
document.querySelector<HTMLButtonElement>("#createWalletButton")?.addEventListener("click", () => {
|
||||
void createWallet();
|
||||
});
|
||||
@@ -668,6 +809,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
document.querySelector<HTMLButtonElement>("#exportWalletTransferButton")?.addEventListener("click", () => {
|
||||
void exportWallet();
|
||||
});
|
||||
document.querySelector<HTMLSelectElement>("#walletExportAliasSelect")?.addEventListener("change", () => {
|
||||
updateExportFileName(false);
|
||||
});
|
||||
document.querySelector<HTMLSelectElement>("#walletExportFormatSelect")?.addEventListener("change", () => {
|
||||
updateExportFileName(false);
|
||||
});
|
||||
document.querySelector<HTMLInputElement>("#walletExportFileNameInput")?.addEventListener("input", event => {
|
||||
const input = event.currentTarget as HTMLInputElement;
|
||||
input.dataset.autoGenerated = "false";
|
||||
});
|
||||
document.querySelector<HTMLInputElement>("#walletImportSourcePathInput")?.addEventListener("input", () => {
|
||||
setTransferPublicKey("");
|
||||
setText("#walletTransferStatus", "En attente");
|
||||
|
||||
Reference in New Issue
Block a user