@tronscan/client
Version:
Tronscan API Client
260 lines (227 loc) • 7.46 kB
JavaScript
const {ADDRESS_PREFIX, ADDRESS_PREFIX_BYTE} = require("./address");
const base64EncodeToString = require("../lib/code").base64EncodeToString;
const {base64DecodeFromString, hexStr2byteArray} = require("../lib/code");
const {encode58, decode58} = require("../lib/base58");
const EC = require('elliptic').ec;
const { keccak256 } = require('js-sha3');
const jsSHA = require("../lib/sha256");
const ADDRESS_SIZE = require("./address").ADDRESS_SIZE;
const { byte2hexStr, byteArray2hexStr } = require("./bytes");
/**
* Sign A Transaction by priKey.
* signature is 65 bytes, r[32] || s[32] || id[1](<27)
* @returns a Transaction object signed
* @param priKeyBytes: privateKey for ECC
* @param transaction: a Transaction object unSigned
*/
function signTransaction(priKeyBytes, transaction) {
if (typeof priKeyBytes === 'string') {
priKeyBytes = hexStr2byteArray(priKeyBytes);
}
let raw = transaction.getRawData();
let rawBytes = raw.serializeBinary();
let hashBytes = SHA256(rawBytes);
let signBytes = ECKeySign(hashBytes, priKeyBytes);
let uint8Array = new Uint8Array(signBytes);
let count = raw.getContractList().length;
for (let i = 0; i < count; i++) {
transaction.addSignature(uint8Array);
}
return {
transaction,
hex: byteArray2hexStr(transaction.serializeBinary()),
};
}
function arrayToBase64String(a) {
return btoa(String.fromCharCode(...a));
}
function signBytes(privateKey, contents) {
if (typeof privateKey === 'string') {
privateKey = hexStr2byteArray(privateKey);
}
let hashBytes = SHA256(contents);
let signBytes = ECKeySign(hashBytes, privateKey);
return signBytes;
}
//return bytes of rowdata, use to sign.
function getRowBytesFromTransactionBase64(base64Data) {
let bytesDecode = base64DecodeFromString(base64Data);
let transaction = proto.protocol.Transaction.deserializeBinary(bytesDecode);
let raw = transaction.getRawData();
return raw.serializeBinary();
}
//gen Ecc priKey for bytes
function genPriKey() {
let ec = new EC('secp256k1');
let key = ec.genKeyPair();
let priKey = key.getPrivate();
let priKeyHex = priKey.toString('hex');
while (priKeyHex.length < 64) {
priKeyHex = "0" + priKeyHex;
}
return hexStr2byteArray(priKeyHex);
}
//return address by bytes, pubBytes is byte[]
function computeAddress(pubBytes) {
if (pubBytes.length === 65) {
pubBytes = pubBytes.slice(1);
}
var hash = keccak256(pubBytes).toString();
var addressHex = hash.substring(24);
addressHex = ADDRESS_PREFIX + addressHex;
return hexStr2byteArray(addressHex);
}
//return address by bytes, priKeyBytes is byte[]
function getAddressFromPriKey(priKeyBytes) {
let pubBytes = getPubKeyFromPriKey(priKeyBytes);
return computeAddress(pubBytes);
}
//return address by Base58Check String,
function getBase58CheckAddress(addressBytes) {
var hash0 = SHA256(addressBytes);
var hash1 = SHA256(hash0);
var checkSum = hash1.slice(0, 4);
checkSum = addressBytes.concat(checkSum);
return encode58(checkSum);
}
function decode58Check(addressStr) {
var decodeCheck = decode58(addressStr);
if (decodeCheck.length <= 4) {
console.error("ERROR CHECK");
return null;
}
var decodeData = decodeCheck.slice(0, decodeCheck.length - 4);
var hash0 = SHA256(decodeData);
var hash1 = SHA256(hash0);
if (hash1[0] === decodeCheck[decodeData.length] &&
hash1[1] === decodeCheck[decodeData.length + 1] &&
hash1[2] === decodeCheck[decodeData.length + 2] &&
hash1[3] === decodeCheck[decodeData.length + 3]) {
return decodeData;
}
return null;
}
function isAddressValid(base58Str) {
try {
if (typeof(base58Str) !== 'string') {
return false;
}
if (base58Str.length !== ADDRESS_SIZE) {
return false;
}
var address = decode58(base58Str);
if (address.length !== 25) {
return false;
}
if (address[0] !== ADDRESS_PREFIX_BYTE) {
return false;
}
var checkSum = address.slice(21);
address = address.slice(0, 21);
var hash0 = SHA256(address);
var hash1 = SHA256(hash0);
var checkSum1 = hash1.slice(0, 4);
if (checkSum[0] == checkSum1[0] && checkSum[1] == checkSum1[1] && checkSum[2]
== checkSum1[2] && checkSum[3] == checkSum1[3]
) {
return true
}
} catch(e) {
// ignore
}
return false;
}
//return address by Base58Check String, priKeyBytes is base64String
function getBase58CheckAddressFromPriKeyBase64String(priKeyBase64String) {
var priKeyBytes = base64DecodeFromString(priKeyBase64String);
var pubBytes = getPubKeyFromPriKey(priKeyBytes);
var addressBytes = computeAddress(pubBytes);
return getBase58CheckAddress(addressBytes);
}
//return address by String, priKeyBytes is base64String
function getHexStrAddressFromPriKeyBase64String(priKeyBase64String) {
let priKeyBytes = base64DecodeFromString(priKeyBase64String);
let pubBytes = getPubKeyFromPriKey(priKeyBytes);
let addressBytes = computeAddress(pubBytes);
let addressHex = byteArray2hexStr(addressBytes);
return addressHex;
}
//return address by String, priKeyBytes is base64String
function getAddressFromPriKeyBase64String(priKeyBase64String) {
let priKeyBytes = base64DecodeFromString(priKeyBase64String);
let pubBytes = getPubKeyFromPriKey(priKeyBytes);
let addressBytes = computeAddress(pubBytes);
let addressBase64 = base64EncodeToString(addressBytes);
return addressBase64;
}
//return pubkey by 65 bytes, priKeyBytes is byte[]
function getPubKeyFromPriKey(priKeyBytes) {
var ec = new EC('secp256k1');
var key = ec.keyFromPrivate(priKeyBytes, 'bytes');
var pubkey = key.getPublic();
var x = pubkey.x;
var y = pubkey.y;
var xHex = x.toString('hex');
while (xHex.length < 64) {
xHex = "0" + xHex;
}
var yHex = y.toString('hex');
while (yHex.length < 64) {
yHex = "0" + yHex;
}
var pubkeyHex = "04" + xHex + yHex;
var pubkeyBytes = hexStr2byteArray(pubkeyHex);
return pubkeyBytes;
}
//return sign by 65 bytes r s id. id < 27
function ECKeySign(hashBytes, priKeyBytes) {
let ec = new EC('secp256k1');
let key = ec.keyFromPrivate(priKeyBytes, 'bytes');
let signature = key.sign(hashBytes);
let r = signature.r;
let s = signature.s;
let id = signature.recoveryParam;
let rHex = r.toString('hex');
while (rHex.length < 64) {
rHex = "0" + rHex;
}
let sHex = s.toString('hex');
while (sHex.length < 64) {
sHex = "0" + sHex;
}
let idHex = byte2hexStr(id);
let signHex = rHex + sHex + idHex;
return hexStr2byteArray(signHex);
}
//toDO:
//return 32 bytes
function SHA256(msgBytes) {
let shaObj = new jsSHA("SHA-256", "HEX");
let msgHex = byteArray2hexStr(msgBytes);
shaObj.update(msgHex);
let hashHex = shaObj.getHash("HEX");
return hexStr2byteArray(hashHex);
}
function passwordToAddress(password) {
let com_priKeyBytes = base64DecodeFromString(password);
let com_addressBytes = getAddressFromPriKey(com_priKeyBytes);
return getBase58CheckAddress(com_addressBytes);
}
function pkToAddress(privateKey) {
let com_priKeyBytes = hexStr2byteArray(privateKey);
let com_addressBytes = getAddressFromPriKey(com_priKeyBytes);
return getBase58CheckAddress(com_addressBytes);
}
module.exports = {
signTransaction,
passwordToAddress,
genPriKey,
getAddressFromPriKey,
getPubKeyFromPriKey,
getBase58CheckAddress,
isAddressValid,
getBase58CheckAddressFromPriKeyBase64String,
pkToAddress,
decode58Check,
signBytes,
};