const CREATE_TOKEN_FEE_ATOMIC = 50000000000n; const TOKEN_ATOMIC_UNITS = 100000000n; function setCreateTokenMessage(message, type = "") { setScopedTransactionMessage("Create Token", createTokenMessage, message, type); } function tokenDecimalToAtomic(value) { const text = String(value || "").trim(); if (!/^\d+(\.\d{0,8})?$/.test(text)) { return null; } const [whole, fraction = ""] = text.split("."); const paddedFraction = fraction.padEnd(8, "0"); return BigInt(whole || "0") * TOKEN_ATOMIC_UNITS + BigInt(paddedFraction || "0"); } function tokenAtomicToDecimal(value) { const atomic = BigInt(value || 0); const whole = atomic / TOKEN_ATOMIC_UNITS; const fraction = String(atomic % TOKEN_ATOMIC_UNITS).padStart(8, "0"); return `${whole}.${fraction}`; } function updateCreateTokenDerivedFields() { if (createTokenFeeInput) { createTokenFeeInput.value = tokenAtomicToDecimal(CREATE_TOKEN_FEE_ATOMIC); } if (createTokenFeeLabel) { createTokenFeeLabel.textContent = `${tokenAtomicToDecimal(CREATE_TOKEN_FEE_ATOMIC)} ${activeBaseCoin()}`; } if (createTokenCap) { createTokenCap.textContent = createTokenAllowMoreInput?.checked ? "Future issuance allowed" : "Hard capped"; } if (createTokenCreator) { createTokenCreator.textContent = activeWalletAddressShort || activeWalletAddressHex || "--"; } } function validateCreateTokenForm() { if (!walletLoaded) { return "Load a wallet before creating a token."; } if (!registrationRegistered) { return "Address registration is required before creating a token."; } const ticker = String(createTokenTickerInput?.value || "").trim(); if (!ticker) { return "Token ticker is required."; } if (!/^[A-Za-z0-9\s]+$/.test(ticker)) { return "Token ticker can only contain letters, numbers, and spaces."; } const canonicalTicker = ticker.replace(/\s+/g, "").toLowerCase(); if (canonicalTicker.length < 3 || canonicalTicker.length > 15) { return "Token ticker must normalize to 3 to 15 letters or numbers."; } if (canonicalTicker.toUpperCase() === activeBaseCoin()) { return "Token ticker is reserved for the base coin."; } const number = tokenDecimalToAtomic(createTokenNumberInput?.value); if (number === null || number <= 0n) { return "Enter a valid initial supply with up to 8 decimal places."; } return ""; } function createTokenPayload() { return { ticker: String(createTokenTickerInput?.value || "").trim(), number: String(tokenDecimalToAtomic(createTokenNumberInput?.value) || 0n), allowMore: Boolean(createTokenAllowMoreInput?.checked), txfee: String(CREATE_TOKEN_FEE_ATOMIC) }; } function clearCreateTokenForm() { if (createTokenTickerInput) { createTokenTickerInput.value = ""; } if (createTokenNumberInput) { createTokenNumberInput.value = ""; } if (createTokenAllowMoreInput) { createTokenAllowMoreInput.checked = false; } updateCreateTokenDerivedFields(); } function setCreateTokenButtonsDisabled(disabled) { document.querySelector("[data-create-token-save]")?.toggleAttribute("disabled", disabled); document.querySelector("[data-create-token-broadcast]")?.toggleAttribute("disabled", disabled); } async function handleCreateTokenAction(action) { const error = validateCreateTokenForm(); if (error) { setCreateTokenMessage(error, "error"); return; } const invoke = window.__TAURI__?.core?.invoke; if (!invoke) { setCreateTokenMessage("Wallet bridge is not available.", "error"); return; } const walletKey = await requestSigningWalletKey(); if (guiRuntimeSettings.require_key_before_signing !== false && !walletKey) { setCreateTokenMessage("Signing cancelled."); return; } setCreateTokenButtonsDisabled(true); try { if (action === "save") { setCreateTokenMessage("Saving token transaction..."); const review = await invoke("save_create_token_transaction", { ...createTokenPayload(), walletKey }); clearCreateTokenForm(); setCreateTokenMessage(`Token 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."); } setCreateTokenMessage("Broadcasting token transaction..."); const result = await invoke("broadcast_create_token_transaction", { ...createTokenPayload(), broadcastNode, walletKey }); if (typeof invalidateAssetsCatalog === "function") { invalidateAssetsCatalog(); } clearCreateTokenForm(); setCreateTokenMessage(result.response || "Token transaction broadcast.", "success"); } } catch (error) { setCreateTokenMessage(String(error), "error"); } finally { setCreateTokenButtonsDisabled(false); } } function prepareCreateTokenForm() { updateCreateTokenDerivedFields(); setCreateTokenMessage(""); } createTokenTickerInput?.addEventListener("input", () => { updateCreateTokenDerivedFields(); setCreateTokenMessage(""); }); createTokenNumberInput?.addEventListener("input", () => setCreateTokenMessage("")); createTokenAllowMoreInput?.addEventListener("change", () => { updateCreateTokenDerivedFields(); setCreateTokenMessage(""); }); document.querySelector("[data-create-token-save]")?.addEventListener("click", () => handleCreateTokenAction("save")); document.querySelector("[data-create-token-broadcast]")?.addEventListener("click", () => handleCreateTokenAction("broadcast"));