Contractless-GUI-Wallet/frontend/js/collateral_claim_form.js

221 lines
8.2 KiB
JavaScript
Raw Permalink Normal View History

2026-07-01 16:01:30 +00:00
const COLLATERAL_CLAIM_FEE_ATOMIC = 300000000n;
let collateralClaimContracts = [];
let collateralClaimLoadPromise = null;
let collateralClaimContractsKey = "";
function setCollateralClaimMessage(message, type = "") {
setScopedTransactionMessage("Collateral Claim", collateralClaimMessage, message, type);
}
function selectedCollateralClaimContract() {
const hash = String(collateralClaimContractSelect?.value || "");
return collateralClaimContracts.find((contract) => contract.contract === hash) || null;
}
function claimAssetLabel(asset, amount) {
return `${atomicToDecimal(BigInt(amount || "0"))} ${String(asset || "").trim()}`.trim();
}
function collateralClaimOptionLabel(contract) {
const role = String(contract.role || "").toLowerCase() === "borrower"
? "reclaim"
: "claim";
return `${role} ${claimAssetLabel(contract.collateral, contract.collateral_amount)} from ${truncateMiddle(contract.contract, 8, 8)}`;
}
function populateCollateralClaimContracts() {
if (!collateralClaimContractSelect) {
return;
}
const previous = collateralClaimContractSelect.value;
collateralClaimContractSelect.innerHTML = "";
if (collateralClaimContracts.length) {
const placeholder = document.createElement("option");
placeholder.value = "";
placeholder.textContent = "Select claimable collateral";
collateralClaimContractSelect.appendChild(placeholder);
}
collateralClaimContracts.forEach((contract) => {
const option = document.createElement("option");
option.value = contract.contract;
option.textContent = collateralClaimOptionLabel(contract);
collateralClaimContractSelect.appendChild(option);
});
if (!collateralClaimContracts.length) {
const option = document.createElement("option");
option.value = "";
option.textContent = "No collateral is currently claimable";
collateralClaimContractSelect.appendChild(option);
} else if ([...collateralClaimContractSelect.options].some((option) => option.value === previous)) {
collateralClaimContractSelect.value = previous;
}
updateCollateralClaimDetails();
}
async function loadCollateralClaimContracts(force = false) {
if (collateralClaimLoadPromise) {
return collateralClaimLoadPromise;
}
const invoke = window.__TAURI__?.core?.invoke;
const broadcastNode = activeBroadcastNode();
if (!invoke || !broadcastNode || !walletLoaded || !registrationRegistered) {
return;
}
const key = `${activeWalletAddressShort || activeWalletAddressHex}|${broadcastNode}`;
if (!force && collateralClaimContractsKey === key) {
populateCollateralClaimContracts();
return;
}
collateralClaimLoadPromise = (async () => {
setCollateralClaimMessage("Loading claimable collateral...");
const contracts = await invoke("claimable_collateral_contracts", { broadcastNode });
collateralClaimContracts = Array.isArray(contracts) ? contracts : [];
collateralClaimContractsKey = key;
populateCollateralClaimContracts();
setCollateralClaimMessage(
collateralClaimContracts.length ? "" : "No collateral is currently claimable."
);
})().catch((error) => {
collateralClaimContracts = [];
populateCollateralClaimContracts();
setCollateralClaimMessage(String(error), "error");
throw error;
}).finally(() => {
collateralClaimLoadPromise = null;
});
return collateralClaimLoadPromise;
}
function updateCollateralClaimDetails() {
const contract = selectedCollateralClaimContract();
if (!contract) {
collateralClaimRole.textContent = "--";
collateralClaimReason.textContent = "--";
collateralClaimLender.textContent = "--";
collateralClaimBorrower.textContent = "--";
collateralClaimLoan.textContent = "--";
collateralClaimCollateral.textContent = "--";
collateralClaimConfirmed.textContent = "--";
collateralClaimRemaining.textContent = "--";
collateralClaimFeeInput.value = atomicToDecimal(COLLATERAL_CLAIM_FEE_ATOMIC);
return;
}
collateralClaimRole.textContent = contract.role === "borrower" ? "Borrower reclaim" : "Lender claim";
collateralClaimReason.textContent = contract.reason || "Collateral claim is currently allowed.";
collateralClaimLender.textContent = contract.lender;
collateralClaimBorrower.textContent = contract.borrower;
collateralClaimLoan.textContent = claimAssetLabel(contract.loan_asset, contract.loan_amount);
collateralClaimCollateral.textContent = claimAssetLabel(contract.collateral, contract.collateral_amount);
collateralClaimConfirmed.textContent = claimAssetLabel(contract.loan_asset, contract.confirmed_paid);
collateralClaimRemaining.textContent = claimAssetLabel(contract.loan_asset, contract.remaining_balance);
collateralClaimFeeInput.value = atomicToDecimal(BigInt(contract.fee || COLLATERAL_CLAIM_FEE_ATOMIC));
}
function validateCollateralClaimForm() {
if (!walletLoaded) {
return "Load a wallet before claiming collateral.";
}
if (!registrationRegistered) {
return "Address registration is required before claiming collateral.";
}
if (!selectedCollateralClaimContract()) {
return "Select claimable collateral.";
}
if (baseCoinBalanceAtomic() < COLLATERAL_CLAIM_FEE_ATOMIC) {
return `Claiming collateral requires ${atomicToDecimal(COLLATERAL_CLAIM_FEE_ATOMIC)} ${activeBaseCoin()} for the transaction fee.`;
}
return "";
}
function collateralClaimPayload() {
return {
broadcastNode: activeBroadcastNode(),
contractHash: selectedCollateralClaimContract().contract
};
}
function setCollateralClaimButtonsDisabled(disabled) {
document.querySelector("[data-collateral-claim-save]")?.toggleAttribute("disabled", disabled);
document.querySelector("[data-collateral-claim-broadcast]")?.toggleAttribute("disabled", disabled);
}
function clearCollateralClaimForm() {
collateralClaimContractSelect.value = "";
updateCollateralClaimDetails();
}
async function handleCollateralClaimAction(action) {
const validationError = validateCollateralClaimForm();
if (validationError) {
setCollateralClaimMessage(validationError, "error");
return;
}
const invoke = window.__TAURI__?.core?.invoke;
if (!invoke) {
setCollateralClaimMessage("Wallet bridge is not available.", "error");
return;
}
const walletKey = await requestSigningWalletKey();
if (guiRuntimeSettings.require_key_before_signing !== false && !walletKey) {
setCollateralClaimMessage("Signing cancelled.");
return;
}
setCollateralClaimButtonsDisabled(true);
try {
if (action === "save") {
setCollateralClaimMessage("Saving collateral claim transaction...");
const review = await invoke("save_collateral_claim_transaction", {
...collateralClaimPayload(),
walletKey
});
clearCollateralClaimForm();
setCollateralClaimMessage(`Collateral claim saved: ${review.file_name}`, "success");
if (typeof refreshUnbroadcastTransactions === "function") {
refreshUnbroadcastTransactions();
}
} else {
setCollateralClaimMessage("Broadcasting collateral claim...");
const result = await invoke("broadcast_collateral_claim_transaction", {
...collateralClaimPayload(),
walletKey
});
await loadCollateralClaimContracts(true);
clearCollateralClaimForm();
setCollateralClaimMessage(result.response || "Collateral claim broadcast.", "success");
}
} catch (error) {
setCollateralClaimMessage(String(error), "error");
await loadCollateralClaimContracts(true).catch(() => {});
} finally {
setCollateralClaimButtonsDisabled(false);
}
}
function prepareCollateralClaimForm() {
setCollateralClaimMessage("");
loadCollateralClaimContracts(false).catch(() => {});
}
function resetCollateralClaimSession() {
collateralClaimContracts = [];
collateralClaimLoadPromise = null;
collateralClaimContractsKey = "";
collateralClaimContractSelect.innerHTML = "";
updateCollateralClaimDetails();
setCollateralClaimMessage("");
}
collateralClaimContractSelect?.addEventListener("change", () => {
setCollateralClaimMessage("");
updateCollateralClaimDetails();
});
document
.querySelector("[data-collateral-claim-save]")
?.addEventListener("click", () => handleCollateralClaimAction("save"));
document
.querySelector("[data-collateral-claim-broadcast]")
?.addEventListener("click", () => handleCollateralClaimAction("broadcast"));