0.886
This commit is contained in:
245
Source/process/api-exchange.js
Normal file
245
Source/process/api-exchange.js
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* @project: TERA
|
||||
* @version: Development (beta)
|
||||
* @license: MIT (not for evil)
|
||||
* @copyright: Yuriy Ivanov 2017-2019 [progr76@gmail.com]
|
||||
* Web: https://terafoundation.org
|
||||
* Twitter: https://twitter.com/terafoundation
|
||||
* Telegram: https://web.telegram.org/#/im?p=@terafoundation
|
||||
*/
|
||||
|
||||
const crypto = require('crypto');
|
||||
WebApi2.CreateAccount = function (Params,response)
|
||||
{
|
||||
if(typeof Params === "object" && Params.Name && Params.PubKey)
|
||||
{
|
||||
var TR = {Type:TYPE_TRANSACTION_CREATE, Currency:Params.Currency, PubKey:GetArrFromHex(Params.PubKey), Name:Params.Name, Smart:Params.Smart,
|
||||
};
|
||||
var Body = BufLib.GetBufferFromObject(TR, FORMAT_CREATE, 1000, {}, 1);
|
||||
Body = Body.slice(0, Body.len + 12);
|
||||
SendTransaction(Body, TR, MIN_POWER_POW_ACC_CREATE_LAST, function (result,TR,Body)
|
||||
{
|
||||
var Result = {result:result < 1 ? 0 : 1, text:TR._text, TxID:GetHexFromArr(TR._TxID.slice(0, TR_TICKET_HASH_LENGTH + 6)), BlockNum:TR._BlockNum,
|
||||
Meta:Params.Meta, };
|
||||
var Str = JSON.stringify(Result);
|
||||
response.end(Str);
|
||||
});
|
||||
return null;
|
||||
}
|
||||
return {result:0, Meta:Params.Meta};
|
||||
};
|
||||
WebApi2.GetBalance = function (Params,response)
|
||||
{
|
||||
if(typeof Params === "object")
|
||||
{
|
||||
var arr = DApps.Accounts.GetRowsAccounts(ParseNum(Params.AccountID), 1);
|
||||
if(arr.length)
|
||||
{
|
||||
var Value = arr[0].Value;
|
||||
var Result = {result:1, SumCOIN:Value.SumCOIN, SumCENT:Value.SumCENT, Meta:Params.Meta, };
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
return {result:0, Meta:Params.Meta};
|
||||
};
|
||||
var MapSendID = {};
|
||||
WebApi2.Send = function (Params,response)
|
||||
{
|
||||
if(typeof Params !== "object")
|
||||
return {result:0};
|
||||
var Coin;
|
||||
if(typeof Params.Amount === "number")
|
||||
Coin = COIN_FROM_FLOAT(Params.Amount);
|
||||
else
|
||||
Coin = Params.Amount;
|
||||
var FromNum = ParseNum(Params.FromID);
|
||||
if(!Coin)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.Amount required"};
|
||||
if(!FromNum)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.FromID required"};
|
||||
if(!Params.FromPrivKey)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.FromPrivKey required"};
|
||||
if(!Params.ToID)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.ToID required"};
|
||||
var ToPubKeyArr = [];
|
||||
var ToID = 0;
|
||||
if(typeof Params.ToID === "string" && Params.ToID.length === 66)
|
||||
ToPubKeyArr = GetArrFromHex(Params.ToID);
|
||||
else
|
||||
ToID = ParseNum(Params.ToID);
|
||||
var DataFrom = DApps.Accounts.ReadState(FromNum);
|
||||
if(!DataFrom)
|
||||
return {result:0, Meta:Params.Meta, text:"Error read account: " + FromNum};
|
||||
var OperationID;
|
||||
if(!MapSendID[FromNum])
|
||||
{
|
||||
OperationID = DataFrom.Value.OperationID + 10;
|
||||
MapSendID[FromNum] = {};
|
||||
}
|
||||
else
|
||||
{
|
||||
OperationID = MapSendID[FromNum].OperationID;
|
||||
if((new Date() - MapSendID[FromNum].Date) > 8 * 1000)
|
||||
{
|
||||
OperationID += 20;
|
||||
}
|
||||
}
|
||||
OperationID++;
|
||||
MapSendID[FromNum].OperationID = OperationID;
|
||||
MapSendID[FromNum].Date = Date.now();
|
||||
var TR = {Type:111, Version:3, Reserve:0, FromID:FromNum, OperationID:OperationID, To:[{PubKey:ToPubKeyArr, ID:ToID, SumCOIN:Coin.SumCOIN,
|
||||
SumCENT:Coin.SumCENT}], Description:Params.Description, Body:[], };
|
||||
TR.Sign = DApps.Accounts.GetSignTransferTx(TR, GetArrFromHex(Params.FromPrivKey));
|
||||
var Body = BufLib.GetBufferFromObject(TR, FORMAT_MONEY_TRANSFER3, MAX_TRANSACTION_SIZE, {}, 1);
|
||||
Body = Body.slice(0, Body.len + 12);
|
||||
SendTransaction(Body, TR, undefined, function (result,TR,Body)
|
||||
{
|
||||
var Result = {result:result < 1 ? 0 : 1, text:TR._text, TxID:GetHexFromArr(TR._TxID.slice(0, TR_TICKET_HASH_LENGTH + 6)), BlockNum:TR._BlockNum,
|
||||
Meta:Params.Meta, };
|
||||
var Str = JSON.stringify(Result);
|
||||
response.end(Str);
|
||||
});
|
||||
return null;
|
||||
};
|
||||
WebApi2.GetTransaction = function (Params)
|
||||
{
|
||||
if(typeof Params === "object" && Params.TxID)
|
||||
{
|
||||
var Arr = GetArrFromHex(Params.TxID);
|
||||
var BlockNum = ReadUintFromArr(Arr, TR_TICKET_HASH_LENGTH);
|
||||
var Block = SERVER.ReadBlockDB(BlockNum);
|
||||
if(Block)
|
||||
{
|
||||
Arr = Arr.slice(0, TR_TICKET_HASH_LENGTH);
|
||||
for(var i = 0; i < Block.arrContent.length; i++)
|
||||
{
|
||||
var Body = Block.arrContent[i];
|
||||
var Nonce = ReadUintFromArr(Body, Body.length - 6);
|
||||
var Arr2 = CreateTxID(Body, BlockNum, Nonce);
|
||||
Arr2 = Arr2.slice(0, TR_TICKET_HASH_LENGTH);
|
||||
if(CompareArr(Arr2, Arr) === 0)
|
||||
{
|
||||
var TR = DApps.Accounts.GetObjectTransaction(Body);
|
||||
if(TR)
|
||||
{
|
||||
ConvertBufferToStr(TR);
|
||||
TR.result = 1;
|
||||
TR.Meta = Params.Meta;
|
||||
return TR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {result:0, Meta:Params.Meta};
|
||||
};
|
||||
WebApi2.GetHistoryTransactions = function (Params)
|
||||
{
|
||||
};
|
||||
WebApi2.GenerateKeys = function (Params)
|
||||
{
|
||||
var KeyPair = crypto.createECDH('secp256k1');
|
||||
var PrivKey = sha3(crypto.randomBytes(32));
|
||||
KeyPair.setPrivateKey(Buffer.from(PrivKey));
|
||||
var PubKey = KeyPair.getPublicKey('', 'compressed');
|
||||
return {result:1, PrivKey:GetHexFromArr(PrivKey), PubKey:GetHexFromArr(PubKey), Meta:Params.Meta};
|
||||
};
|
||||
var DELTA_FOR_TIME_TX = 1;
|
||||
|
||||
function CreateTxID(body,BlockNum,Nonce)
|
||||
{
|
||||
body.writeUIntLE(BlockNum, body.length - 12, 6);
|
||||
body.writeUIntLE(Nonce, body.length - 6, 6);
|
||||
var HASH = sha3(body);
|
||||
var FullHashTicket = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
for(var i = 0; i < TR_TICKET_HASH_LENGTH; i++)
|
||||
FullHashTicket[i] = HASH[i];
|
||||
WriteUintToArrOnPos(FullHashTicket, BlockNum, TR_TICKET_HASH_LENGTH);
|
||||
return FullHashTicket;
|
||||
};
|
||||
|
||||
function GetBlockNumTr(arr)
|
||||
{
|
||||
var BlockNum = DELTA_FOR_TIME_TX + GetCurrentBlockNumByTime();
|
||||
if(arr[0] === TYPE_TRANSACTION_CREATE)
|
||||
{
|
||||
var BlockNum2 = Math.floor(BlockNum / 10) * 10;
|
||||
if(BlockNum2 < BlockNum)
|
||||
BlockNum2 = BlockNum2 + 10;
|
||||
BlockNum = BlockNum2;
|
||||
}
|
||||
return BlockNum;
|
||||
};
|
||||
|
||||
function CreateHashBodyPOWInnerMinPower(TR,arr,MinPow,startnonce)
|
||||
{
|
||||
var BlockNum = GetBlockNumTr(arr);
|
||||
if(MinPow === undefined)
|
||||
{
|
||||
MinPow = MIN_POWER_POW_TR + Math.log2(arr.length / 128);
|
||||
}
|
||||
var nonce = startnonce;
|
||||
while(1)
|
||||
{
|
||||
var TxID = CreateTxID(arr, BlockNum, nonce);
|
||||
var power = GetPowPower(sha3(TxID));
|
||||
if(power >= MinPow)
|
||||
{
|
||||
TR._TxID = TxID;
|
||||
TR._BlockNum = BlockNum;
|
||||
ToLog("Find: " + power + " for block:" + BlockNum);
|
||||
return nonce;
|
||||
}
|
||||
nonce++;
|
||||
if(nonce % 2000 === 0)
|
||||
{
|
||||
BlockNum = GetBlockNumTr(arr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function SendTransaction(Body,TR,SumPow,F)
|
||||
{
|
||||
if(Body.length > 16000)
|
||||
{
|
||||
TR._result = 0;
|
||||
TR._text = "Error length transaction =" + Body.length + " (max size=16000)";
|
||||
F(1, TR, Body);
|
||||
return ;
|
||||
}
|
||||
CreateNonceAndSend(0, 0);
|
||||
|
||||
function CreateNonceAndSend(startnonce,NumNext)
|
||||
{
|
||||
if(!NumNext)
|
||||
NumNext = 0;
|
||||
if(NumNext > 10)
|
||||
{
|
||||
F(0, TR, Body);
|
||||
return ;
|
||||
}
|
||||
var nonce = CreateHashBodyPOWInnerMinPower(TR, Body, SumPow, startnonce);
|
||||
process.RunRPC("AddTransactionFromWeb", GetHexFromArr(Body), function (Err,text)
|
||||
{
|
||||
TR._result = Err ? 0 : 1;
|
||||
TR._text = text;
|
||||
if(text === "Not add" || text === "Bad PoW")
|
||||
{
|
||||
CreateNonceAndSend(nonce + 1, NumNext + 1);
|
||||
return ;
|
||||
}
|
||||
else
|
||||
if(text === "Bad time")
|
||||
{
|
||||
if(DELTA_FOR_TIME_TX < 6)
|
||||
{
|
||||
DELTA_FOR_TIME_TX++;
|
||||
ToLog("New set Delta time: " + DELTA_FOR_TIME_TX);
|
||||
CreateNonceAndSend(0, NumNext + 1);
|
||||
return ;
|
||||
}
|
||||
}
|
||||
F(TR._result, TR, Body);
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -72,7 +72,7 @@ process.on('error', function (err)
|
||||
});
|
||||
var ArrChildProcess = [];
|
||||
var WebProcess = {Name:"WEB PROCESS", idInterval:0, idInterval1:0, idInterval2:0, LastAlive:Date.now(), Worker:undefined, Path:"./process/web-process.js",
|
||||
OnMessage:OnMessageWeb, PeriodAlive:3000};
|
||||
OnMessage:OnMessageWeb, PeriodAlive:20 * 1000};
|
||||
if(global.HTTP_HOSTING_PORT && !global.NWMODE)
|
||||
{
|
||||
ArrChildProcess.push(WebProcess);
|
||||
|
||||
@@ -271,6 +271,7 @@ WalletFileMap["style.css"] = 1;
|
||||
WalletFileMap["wallet.css"] = 1;
|
||||
WalletFileMap["blockviewer.html"] = 1;
|
||||
WalletFileMap["web-wallet.html"] = 1;
|
||||
global.WebApi2 = {};
|
||||
global.HostingCaller = {};
|
||||
|
||||
function DoCommandNew(response,Type,Path,Params)
|
||||
@@ -278,12 +279,35 @@ function DoCommandNew(response,Type,Path,Params)
|
||||
if(Path.substring(0, 1) === "/")
|
||||
Path = Path.substring(1);
|
||||
var ArrPath = Path.split('/', 3);
|
||||
var Caller = HostingCaller;
|
||||
var Method = ArrPath[0];
|
||||
var F = HostingCaller[Method];
|
||||
if(ArrPath[0] === "api")
|
||||
{
|
||||
if(ArrPath[1] === "v2")
|
||||
{
|
||||
if(!global.USE_HARD_API_V2)
|
||||
{
|
||||
response.writeHead(200, {'Content-Type':'text/plain', 'Access-Control-Allow-Origin':"*"});
|
||||
response.end(JSON.stringify({result:0, text:"You must set const USE_HARD_API_V2:1"}));
|
||||
return ;
|
||||
}
|
||||
Caller = WebApi2;
|
||||
}
|
||||
Method = ArrPath[2];
|
||||
}
|
||||
var F = Caller[Method];
|
||||
if(F)
|
||||
{
|
||||
response.writeHead(200, {'Content-Type':'text/plain', 'Access-Control-Allow-Origin':"*"});
|
||||
var Ret = F(Params, response);
|
||||
var Ret;
|
||||
try
|
||||
{
|
||||
Ret = F(Params, response);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
Ret = {result:0, text:e.message, text2:e.stack};
|
||||
}
|
||||
if(Ret === null)
|
||||
return ;
|
||||
try
|
||||
@@ -382,7 +406,7 @@ HostingCaller.GetCurrentInfo = function (Params)
|
||||
{
|
||||
var Ret = {result:1, VersionNum:global.UPDATE_CODE_VERSION_NUM, MaxNumBlockDB:SERVER.GetMaxNumBlockDB(), CurBlockNum:GetCurrentBlockNumByTime(),
|
||||
MaxAccID:DApps.Accounts.GetMaxAccount(), MaxDappsID:DApps.Smart.GetMaxNum(), NETWORK:global.NETWORK, CurTime:Date.now(), DELTA_CURRENT_TIME:DELTA_CURRENT_TIME,
|
||||
MIN_POWER_POW_TR:MIN_POWER_POW_TR, FIRST_TIME_BLOCK:FIRST_TIME_BLOCK, CONSENSUS_PERIOD_TIME:CONSENSUS_PERIOD_TIME, MIN_POWER_POW_ACC_CREATE:MIN_POWER_POW_ACC_CREATE,
|
||||
MIN_POWER_POW_TR:MIN_POWER_POW_TR, FIRST_TIME_BLOCK:FIRST_TIME_BLOCK, CONSENSUS_PERIOD_TIME:CONSENSUS_PERIOD_TIME, MIN_POWER_POW_ACC_CREATE:MIN_POWER_POW_ACC_CREATE_LAST,
|
||||
};
|
||||
if(typeof Params === "object" && Params.Diagram == 1)
|
||||
{
|
||||
@@ -745,3 +769,4 @@ setInterval(function ()
|
||||
NodeBlockChain = BufWrite;
|
||||
}
|
||||
}, 1000);
|
||||
require("./api-exchange.js");
|
||||
|
||||
Reference in New Issue
Block a user