/* * @project: TERA * @version: Development (beta) * @license: MIT (not for evil) * @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com] * Web: https://terafoundation.org * Twitter: https://twitter.com/terafoundation * Telegram: https://t.me/terafoundation */ var PayList = []; var AttachItem; var MapAccounts = {}; var LoadMapAfter = {}; var MapCheckTransaction = {}; var CanSendTransaction = 1; var CurrentTR = {}; var MaxBlockNum = 0; var DelList = {}; var WasAccountsDataStr; function SetAccountsData(Data,AccountsDataStr) { if(!Data || !Data.result) return ; if($("idBtRun")) $("idBtRun").style.display = (Data.arr.length ? '' : 'none'); if(AccountsDataStr === WasAccountsDataStr) return ; WasAccountsDataStr = AccountsDataStr; var arr = Data.arr; var Select = $("idAccount"); if(arr.length !== Select.options.length) { var options = Select.options; options.length = arr.length; } MaxBlockNum = GetCurrentBlockNumByTime(); SetGridData(arr, "grid_accounts", "idMyTotalSum"); for(var i = 0; arr && i < arr.length; i++) { var Item = arr[i]; Item.MyAccount = true; var Num = ParseNum(Item.Num); if(!MapAccounts[Num]) MapAccounts[Num] = {}; CopyObjKeys(MapAccounts[Num], Item); var option = Select.options[i]; var StrText = GetAccountText(Item, Num, 1); if(option.text !== StrText) CheckNameAccTo(); option.value = Num; option.text = StrText; } var CurentValue = LoadMapAfter["idAccount"]; if(CurentValue) { Select.value = CurentValue; delete LoadMapAfter["idAccount"]; } SetCurCurencyName(); }; function CurTransactionToForm(bForce) { var Item = $("idTransaction"); if(Item && (Item.className === "" || bForce)) Item.value = GetJSONFromTransaction(CurrentTR); }; function CheckNameAccTo() { MaxBlockNum = GetCurrentBlockNumByTime(); var ToID = ParseNum($("idTo").value); if(!MapAccounts[ToID] || (MapAccounts[ToID].MustUpdate && MapAccounts[ToID].MustUpdate >= MaxBlockNum)) { GetData("GetAccountList", {StartNum:ToID}, function (Data) { if(Data && Data.result === 1 && Data.arr.length) { var Item = Data.arr[0]; Item.UpdateData = Date.now(); MapAccounts[Item.Num] = Item; SetNameAccTo(); } }); } SetNameAccTo(); }; function SetNameAccTo() { var Str = ""; var ToID = $("idTo").value.trim(); var Item = MapAccounts[ToID]; var StrTo = GetAccountText(Item, ToID, 1); var element = $("idNameTo"); if(!element) { element = $("idNameTo2"); } else { StrTo = "To: " + StrTo; } if(!ToID || ToID === "0") { element.innerText = ""; return ; } if(element && element.innerText !== StrTo) { element.innerText = StrTo; if(Item && Item.MyAccount) element.className = "smallbold"; else element.className = ""; } }; function GetAccountText(Item,Num,bGetSum) { if(Item) { var text = Item.Name; if(!text || text.length === 0) text = Num; else text = "" + Num + ". " + text; if(bGetSum) { var StrSum = SUM_TO_STRING(Item.Value, Item.Currency); text += " (" + StrSum + ")"; } return text; } else { if(IsPublicAddr(Num)) return Num; else return ""; } }; function OnEditIdTo() { CheckNameAccTo(); OnEditTransactionFields(); }; function OnEditTransactionFields() { if(IsVisibleBlock("edit_transaction")) CreateTransaction(); SetCurCurencyName(); SaveValues(); }; function SetCurCurencyName() { var idCoin = $("idCoinName"); if(!idCoin) return ; var Num = ParseNum($("idAccount").value); var Item = MapAccounts[Num]; if(Item) { idCoin.innerText = CurrencyName(Item.Currency); } }; function IsPublicAddr(StrTo) { if(StrTo.length === 66 && (StrTo.substr(0, 2) === "02" || StrTo.substr(0, 2) === "03") && IsHexStr(StrTo)) return 1; else return 0; }; function CreateTransaction(F,CheckErr,Run) { CheckNameAccTo(); CheckSending(); var FromID = ParseNum($("idAccount").value); if(CheckErr && FromID === 0) { SetError("Select valid 'From account'"); return ; } var StrTo = $("idTo").value.trim(); var bFindAcc = 0; var ToPubKey = ""; var ToID = ParseNum(StrTo); if(StrTo !== "" + ToID) { if(IsPublicAddr(StrTo)) { ToID = 0; ToPubKey = StrTo; if(ToPubKey === window.PubKeyStr) bFindAcc = 1; } else { if(CheckErr) SetError("Valid 'Pay to' - required!"); return ; } } if(CheckErr && ToID <= 0 && ToPubKey === "" && !AttachItem) { SetError("Valid 'Pay to' - required!"); return ; } var Description = $("idDescription").value.substr(0, 200); var StrSum = $("idSumSend").value; var indDot = StrSum.indexOf("."); if(indDot >= 0) { var StrTER = StrSum.substr(0, indDot); var StrCENT = StrSum.substr(indDot + 1); } else { var StrTER = StrSum; var StrCENT = "0"; } StrCENT = StrCENT + "000000000"; var Coin = {SumCOIN:ParseNum(StrTER), SumCENT:ParseNum(StrCENT.substr(0, 9))}; var OperationID = 0; var Item = MapAccounts[FromID]; if(Item) { OperationID = Item.Value.OperationID; } var AttachBody = []; if(AttachItem) { AttachBody = AttachItem.Data.Body; if(!AttachBody) AttachBody = []; } var ToPubKeyArr = []; if(ToPubKey) ToPubKeyArr = GetArrFromHex(ToPubKey); var TR = {Type:111, Version:3, Reserve:0, FromID:FromID, OperationID:OperationID, To:[{PubKey:ToPubKeyArr, ID:ToID, SumCOIN:Coin.SumCOIN, SumCENT:Coin.SumCENT}], Description:Description, Body:AttachBody, Sign:CurrentTR.Sign, }; Object.defineProperties(TR, {bFindAcc:{configurable:true, writable:true, enumerable:false, value:bFindAcc}}); Object.defineProperties(TR, {Run:{configurable:true, writable:true, enumerable:false, value:Run}}); if(JSON.stringify(TR) === JSON.stringify(CurrentTR)) { if(F) F(CurrentTR); return ; } CurrentTR = TR; GetSignTransaction(TR, "", function (TR) { CurTransactionToForm(true); if(F) F(TR); }); }; function SignJSON(F) { if($("idSignJSON").disabled) return ; var TR = GetTransactionFromJSON(); if(!TR) return ; CurrentTR = TR; GetSignTransaction(TR, "", function (TR) { CurTransactionToForm(true); if(F) F(); }); }; function CheckSending(bToStatus) { MaxBlockNum = GetCurrentBlockNumByTime(); var CanSend = IsPrivateMode(); var StrButton = "Send"; var StrButtonSign = "Sign JSON"; if(!CanSend) { StrButton = " "; StrButtonSign = " "; } if(CanSend) { var FromID = ParseNum($("idAccount").value); var Item = MapAccounts[FromID]; if(Item && Item.NextSendTime && Item.NextSendTime > MaxBlockNum) { if(bToStatus) SetStatus("Transaction was sending. Wait... (" + Item.LastTransactionText + ")"); CanSend = false; StrButton = "Wait..."; } } $("idSendButton").disabled = (!CanSend); $("idSendButton").value = StrButton; $("idSignJSON").disabled = (!CanSend); $("idSignJSON").value = StrButtonSign; return CanSend; }; function AddWhiteList() { var ToID = ParseNum($("idTo").value); if(ToID && $("idWhiteOnSend").checked) Storage.setItem("White:" + ToID, 1); }; function SendMoneyBefore() { if($("idSendButton").disabled) return ; var ToID = ParseNum($("idTo").value); var Item = MapAccounts[ToID]; if(Storage.getItem("White:" + ToID) || !$("idSumSend").value || Item && Item.MyAccount) { SendMoney(); } else { var CoinAmount = COIN_FROM_FLOAT($("idSumSend").value); var StrTo = " to " + GetAccountText(Item, ToID); $("idWhiteOnSend").checked = 0; $("idOnSendText").innerHTML = "" + STRING_FROM_COIN(CoinAmount) + " " + $("idCoinName").innerText + StrTo; if($("idSumSend").value >= 100000) { $("idOnSendText").innerHTML += "
WARNING: You are about to send a very large amount!
"; } SetVisibleBlock("idBlockOnSend", 1); SetImg(this, 'idBlockOnSend'); } }; function SendMoney2() { AddWhiteList(); SendMoney(); }; function SendMoney(F) { if(!CanSendTransaction) { SetError("Can't Send transaction"); return ; } CheckSending(true); if($("idSendButton").disabled) return ; SetVisibleBlock("idBlockOnSend", 0); if(!F) F = ClearAttach; CreateTransaction(SendMoneyTR, true, F); }; function GetJSONFromTransaction(TR) { var TR2 = JSON.parse(JSON.stringify(TR)); for(var i = 0; i < TR2.To.length; i++) { var Item = TR2.To[i]; Item.PubKey = GetHexFromArr(Item.PubKey); } TR2.Body = GetHexFromArr(TR2.Body); TR2.Sign = GetHexFromArr(TR2.Sign); var Str = JSON.stringify(TR2, "", 4); return Str; }; function GetTransactionFromJSON() { var Str = $("idTransaction").value; try { var TR = JSON.parse(Str); } catch(e) { SetError(e); return undefined; } for(var i = 0; i < TR.To.length; i++) { var Item = TR.To[i]; Item.PubKey = GetArrFromHex(Item.PubKey); if(Item.SumTER && Item.SumCOIN === undefined) { Item.SumCOIN = Item.SumTER; delete Item.SumTER; } } TR.Body = GetArrFromHex(TR.Body); TR.Sign = GetArrFromHex(TR.Sign); return TR; }; function SendMoneyJSON() { if(!CanSendTransaction) { SetError("Can't Send transaction"); return ; } var TR = GetTransactionFromJSON(); if(!TR) return ; SendMoneyTR(TR); }; function SignAndSendFromJSON() { SignJSON(SendMoneyJSON); }; function GetTransactionText(TR,key) { var Str; if(TR) { if(TR.Type === TYPE_TRANSACTION_CREATE) { Str = "New account " + TR.Name.substr(0, 20); } else if(TR.Type === 111) { var MapItem = {}; var ValueTotal = {SumCOIN:0, SumCENT:0}; Str = "" + TR.FromID + "/" + TR.OperationID + " to "; for(var i = 0; i < TR.To.length; i++) { var Item = TR.To[i]; if(Item.ID === TR.FromID || MapItem[Item.ID]) continue; MapItem[Item.ID] = 1; ADD(ValueTotal, Item); if(i === 0) Str += "["; if(Str.length < 16) { if(i > 0) Str += ","; if(Item.ID || (Item.PubKey && Item.PubKey.length !== 66)) Str += Item.ID; else Str += GetHexFromArr(Item.PubKey).substr(0, 8); } else if(Str.substr(Str.length - 1) !== ".") Str += "..."; } Str += "] " + SUM_TO_STRING(ValueTotal); Str += " " + (TR.Description.substr(0, 20)).replace(/\n/g, ""); } } else { if(key) Str = key; else Str = ""; } return Str; }; function SendMoneyTR(TR) { var Body = GetArrFromTR(TR); WriteArr(Body, TR.Sign, 64); Body.length += 12; SendTransaction(Body, TR, undefined, function (Err,TR,Body) { if(Err) return ; var Item = MapAccounts[TR.FromID]; if(Item) { var key = GetHexFromArr(sha3(Body)); var BlockNum = GetCurrentBlockNumByTime(); Item.LastTransactionText = GetTransactionText(TR); Item.NextSendTime = BlockNum + 10; MapCheckTransaction[key] = Item; CheckSending(); } }); }; function ClearTransaction() { PayList = []; ClearAttach(); CheckSendList(1); var arr = ["idAccount", "idTo", "idSumSend", "idDescription"]; for(var i = 0; i < arr.length; i++) { $(arr[i]).value = ""; } SaveValues(); CreateTransaction(); }; function StartEditTransactionJSON() { var Item = $("idTransaction"); Item.className = "smallbold"; }; function EditJSONTransaction() { var name = "edit_transaction"; var Item = $("idTransaction"); if(IsVisibleBlock(name)) { SetVisibleBlock(name, false); Item.className = ""; } else { CreateTransaction(); SetVisibleBlock(name, true); Item.className = ""; } }; var glNumPayCount = 0; function GetInvoiceHTML(item,onclick,classstr) { if(!item.num) { glNumPayCount++; item.num = glNumPayCount; } var idname = "idSendInvoice" + item.num; var value = ""; if(item.Data.Amount) value += "" + item.Data.Amount + " Tera"; else value += "No pay"; value += " " + item.num + ". " + item.Data.name; return ""; }; function AddSendList(item) { PayList.push({Data:item}); }; function CheckSendList(bRedraw) { TitleWarning = PayList.length; if(AttachItem) TitleWarning++; var Str = Storage.getItem("InvoiceList"); if(!Str && !bRedraw) return ; if(!bRedraw) { SelectTab("TabSend"); } if(Str) { var arr = JSON.parse(Str); for(var i = 0; i < arr.length; i++) { AddSendList(arr[i]); } Storage.setItem("InvoiceList", ""); } var idList = $("idSendList"); if(PayList.length) { idList.innerHTML = "
Select the item you want to sign (pay) and send to blockchain:
"; for(var i = 0; i < PayList.length; i++) { var item = PayList[i]; idList.innerHTML += GetInvoiceHTML(item, "UseInvoice(" + i + ")", "btinvoice"); } if(AttachItem === undefined) UseInvoice(0); } else { idList.innerHTML = ""; } }; setInterval(CheckSendList, 200); function UseInvoice(Num) { var item = PayList[Num]; if(item.Data.From) $("idAccount").value = item.Data.From; $("idTo").value = item.Data.To; $("idSumSend").value = item.Data.Amount; $("idDescription").value = item.Data.Description; PayList.splice(Num, 1); AttachItem = item; $("idAttach").innerHTML = GetInvoiceHTML(AttachItem, "OpenAttach()", "btinvoice btinvoice_use"); CheckSendList(1); }; function ClearAttach() { AttachItem = undefined; if($("idAttach")) $("idAttach").innerHTML = ""; }; function OpenAttach() { if(AttachItem) { var Data2 = JSON.parse(JSON.stringify(AttachItem.Data)); if(Data2.Body) Data2.Body = GetHexFromArr(Data2.Body); delete Data2.TransferSecret; alert("DATA:\n" + JSON.stringify(Data2, "", 4)); } }; var CURRENCY, PUBKEY, NAME, SMART; function SendTrCreateAccWait(Currency,PubKey,Name,Smart) { CURRENCY = Currency; PUBKEY = PubKey; NAME = Name; SMART = Smart; setTimeout(function () { SendTrCreateAcc(CURRENCY, PUBKEY, NAME, 0, SMART, 0, 0); }, 50); }; function SendTrCreateAcc(Currency,PubKey,Description,Adviser,Smart,bFindAcc,bAddToPay) { var TR = GetTrCreateAcc(Currency, PubKey, Description, Adviser, Smart); var Body = GetBodyCreateAcc(TR); TR.bFindAcc = 1; if(bAddToPay) { var Item = {name:Description, To:0, Amount:CONFIG_DATA.PRICE_DAO.NewAccount, Description:"Create acc: " + Description, Body:Body, }; AddToInvoiceList(Item); } else { SendTransaction(Body, TR); } $("idAccountName").value = ""; CancelCreateAccount(); }; function DoChangeSmart(NumAccount,WasSmart,SmartNum) { if(SmartNum !== null && SmartNum != WasSmart) { var Smart = parseInt(SmartNum); if(Smart) { GetData("GetDappList", {StartNum:Smart, CountNum:1}, function (Data) { if(Data && Data.result && Data.arr.length === 1) { SetSmartToAccount(NumAccount, Smart); } else { SetError("Error smart number"); } }); } else { SetSmartToAccount(NumAccount, Smart); } } }; function ChangeSmart(NumAccount,WasSmart) { if(!IsPrivateMode()) { SetError("Pls, open wallet"); return 0; } var SmartNum = prompt("Enter smart number:", WasSmart); DoChangeSmart(NumAccount, WasSmart, SmartNum); }; function SetSmartToAccount(NumAccount,Smart) { var OperationID = 0; var Item = MapAccounts[NumAccount]; if(Item) { OperationID = Item.Value.OperationID; } OperationID++; var TR = {Type:140, Account:NumAccount, Smart:Smart, FromNum:NumAccount, Reserve:[], OperationID:OperationID, Sign:"", }; var Body = []; WriteByte(Body, TR.Type); WriteUint(Body, TR.Account); WriteUint32(Body, TR.Smart); WriteArr(Body, TR.Reserve, 10); WriteUint(Body, TR.FromNum); WriteUint(Body, TR.OperationID); SendTrArrayWithSign(Body, TR.Account, TR); }; function CheckLengthAccDesription(name,Length) { var Str = $(name).value.substr(0, Length + 1); var arr = toUTF8Array(Str); var Len = Length - arr.length; if(Len < 0) SetError("Bad length"); else SetStatus("Lost: " + Len + " bytes"); };