const BURN_FEE_ATOMIC = 10000n; let burnBalancesRefreshPromise = null; function setBurnMessage(message, type = "") { setScopedTransactionMessage("Burn", burnMessage, message, type); } function burnableBalances() { return (Array.isArray(activeWalletBalances) ? activeWalletBalances : []) .filter((balance) => { const asset = String(balance.asset || "").trim(); return asset && !isBaseTransferAsset(asset) && balanceAtomicValue(balance) > 0n; }); } function burnAssetOptionLabel(balance) { const amount = formatAtomicBalance(balance.balance || "0"); const series = Number(balance.nft_series || 0); if (series > 0) { return `${balance.asset} #${series} (${amount})`; } return `${balance.asset} (${amount})`; } function selectedBurnAsset() { const option = burnAssetSelect?.selectedOptions?.[0]; if (!option?.value) { return null; } return { asset: option.dataset.asset || "", nftSeries: Number(option.dataset.nftSeries || 0), balance: BigInt(option.dataset.balance || "0") }; } function populateBurnAssets() { if (!burnAssetSelect) { return; } const previous = burnAssetSelect.value; burnAssetSelect.innerHTML = ""; const balances = burnableBalances(); if (balances.length) { const placeholder = document.createElement("option"); placeholder.value = ""; placeholder.textContent = "Select an asset"; burnAssetSelect.appendChild(placeholder); } balances.forEach((balance) => { const option = document.createElement("option"); option.value = transferAssetKey(balance); option.dataset.asset = balance.asset || ""; option.dataset.nftSeries = String(balance.nft_series || 0); option.dataset.balance = String(balance.balance || "0"); option.textContent = burnAssetOptionLabel(balance); burnAssetSelect.appendChild(option); }); if (!balances.length) { const option = document.createElement("option"); option.value = ""; option.textContent = "No burnable assets"; burnAssetSelect.appendChild(option); } else if ([...burnAssetSelect.options].some((option) => option.value === previous)) { burnAssetSelect.value = previous; } updateBurnDerivedFields(); } async function ensureBurnBalances() { if (activeWalletBalances.length || !walletLoaded || !registrationRegistered) { return; } const invoke = window.__TAURI__?.core?.invoke; const broadcastNode = activeBroadcastNode(); if (!invoke || !broadcastNode) { return; } burnBalancesRefreshPromise ||= invoke("get_active_wallet_balances", { broadcastNode }) .then((balances) => { activeWalletBalances = Array.isArray(balances) ? balances : []; }) .finally(() => { burnBalancesRefreshPromise = null; }); await burnBalancesRefreshPromise; } function updateBurnDerivedFields() { const selected = selectedBurnAsset(); if (burnFeeInput) { burnFeeInput.value = atomicToDecimal(BURN_FEE_ATOMIC); } if (burnFeeLabel) { burnFeeLabel.textContent = `${atomicToDecimal(BURN_FEE_ATOMIC)} ${activeBaseCoin()}`; } if (burnAddress) { burnAddress.textContent = activeWalletAddressShort || activeWalletAddressHex || "--"; } if (!selected) { if (burnAvailable) { burnAvailable.textContent = "--"; } if (burnType) { burnType.textContent = "--"; } if (burnAmountInput) { burnAmountInput.disabled = false; burnAmountInput.value = ""; } return; } const isNft = selected.nftSeries > 0; if (burnAvailable) { burnAvailable.textContent = `${atomicToDecimal(selected.balance)} ${selected.asset}`; } if (burnType) { burnType.textContent = isNft ? `NFT #${selected.nftSeries}` : "Token"; } if (burnAmountInput) { burnAmountInput.disabled = isNft; if (isNft) { burnAmountInput.value = "1.00000000"; } } } function validateBurnForm() { if (!walletLoaded) { return "Load a wallet before burning an asset."; } if (!registrationRegistered) { return "Address registration is required before burning an asset."; } const selected = selectedBurnAsset(); if (!selected) { return "Select an asset to burn."; } const amount = decimalToAtomic(burnAmountInput?.value); if (amount === null || amount <= 0n) { return "Enter a valid burn amount."; } if (selected.nftSeries > 0 && amount !== ATOMIC_UNITS_PER_COIN) { return "NFT burns must destroy exactly 1.00000000 units."; } if (amount > selected.balance) { return "Burn amount cannot exceed the selected asset balance."; } if (baseCoinBalanceAtomic() < BURN_FEE_ATOMIC) { return `Burning requires ${atomicToDecimal(BURN_FEE_ATOMIC)} ${activeBaseCoin()} for the transaction fee.`; } return ""; } function burnPayload() { const selected = selectedBurnAsset(); return { coin: selected.asset, nftSeries: selected.nftSeries, value: String(decimalToAtomic(burnAmountInput.value)), txfee: String(BURN_FEE_ATOMIC) }; } function clearBurnForm() { if (burnAssetSelect) { burnAssetSelect.value = ""; } if (burnAmountInput) { burnAmountInput.value = ""; burnAmountInput.disabled = false; } updateBurnDerivedFields(); } function setBurnButtonsDisabled(disabled) { document.querySelector("[data-burn-save]")?.toggleAttribute("disabled", disabled); document.querySelector("[data-burn-broadcast]")?.toggleAttribute("disabled", disabled); } async function handleBurnAction(action) { try { await ensureBurnBalances(); populateBurnAssets(); } catch (error) { setBurnMessage(String(error), "error"); return; } const validationError = validateBurnForm(); if (validationError) { setBurnMessage(validationError, "error"); return; } const invoke = window.__TAURI__?.core?.invoke; if (!invoke) { setBurnMessage("Wallet bridge is not available.", "error"); return; } const walletKey = await requestSigningWalletKey(); if (guiRuntimeSettings.require_key_before_signing !== false && !walletKey) { setBurnMessage("Signing cancelled."); return; } setBurnButtonsDisabled(true); try { if (action === "save") { setBurnMessage("Saving burn transaction..."); const review = await invoke("save_burn_transaction", { ...burnPayload(), walletKey }); clearBurnForm(); setBurnMessage(`Burn transaction saved: ${review.file_name}`, "success"); if (typeof refreshUnbroadcastTransactions === "function") { refreshUnbroadcastTransactions(); } } else { const broadcastNode = activeBroadcastNode(); if (!broadcastNode) { throw new Error("Select a broadcast node before broadcasting."); } setBurnMessage("Broadcasting burn transaction..."); const result = await invoke("broadcast_burn_transaction", { ...burnPayload(), broadcastNode, walletKey }); if (typeof invalidateAssetsCatalog === "function") { invalidateAssetsCatalog(); } activeWalletBalances = []; clearBurnForm(); setBurnMessage(result.response || "Burn transaction broadcast.", "success"); } } catch (error) { setBurnMessage(String(error), "error"); } finally { setBurnButtonsDisabled(false); } } async function prepareBurnForm() { setBurnMessage(""); try { await ensureBurnBalances(); } catch (error) { setBurnMessage(String(error), "error"); } populateBurnAssets(); } function resetBurnSession() { burnBalancesRefreshPromise = null; clearBurnForm(); setBurnMessage(""); } burnAssetSelect?.addEventListener("change", () => { setBurnMessage(""); updateBurnDerivedFields(); }); burnAmountInput?.addEventListener("input", () => setBurnMessage("")); document .querySelector("[data-burn-save]") ?.addEventListener("click", () => handleBurnAction("save")); document .querySelector("[data-burn-broadcast]") ?.addEventListener("click", () => handleBurnAction("broadcast"));