mirror of
https://github.com/Qortal/qortal-ui.git
synced 2025-02-11 17:55:51 +00:00
327 lines
9.9 KiB
JavaScript
327 lines
9.9 KiB
JavaScript
// QORA
|
|
|
|
const TYPES = {
|
|
GENESIS_TRANSACTION: 1,
|
|
PAYMENT_TRANSACTION: 2,
|
|
|
|
REGISTER_NAME_TRANSACTION: 3,
|
|
UPDATE_NAME_TRANSACTION: 4,
|
|
SELL_NAME_TRANSACTION: 5,
|
|
CANCEL_SELL_NAME_TRANSACTION: 6,
|
|
BUY_NAME_TRANSACTION: 7,
|
|
|
|
CREATE_POLL_TRANSACTION: 8,
|
|
VOTE_ON_POLL_TRANSACTION: 9,
|
|
|
|
ARBITRARY_TRANSACTION: 10,
|
|
|
|
ISSUE_ASSET_TRANSACTION: 11,
|
|
TRANSFER_ASSET_TRANSACTION: 12,
|
|
CREATE_ORDER_TRANSACTION: 13,
|
|
CANCEL_ORDER_TRANSACTION: 14,
|
|
MULTI_PAYMENT_TRANSACTION: 15,
|
|
|
|
DEPLOY_AT_TRANSACTION: 16,
|
|
|
|
MESSAGE_TRANSACTION: 17
|
|
};
|
|
|
|
function getKeyPairFromSeed(seed, returnBase58) {
|
|
if (typeof (seed) == "string") {
|
|
seed = new Uint8Array(Base58.decode(seed));
|
|
}
|
|
|
|
var keyPair = nacl.sign.keyPair.fromSeed(seed);
|
|
|
|
var base58privateKey = Base58.encode(keyPair.secretKey);
|
|
var base58publicKey = Base58.encode(keyPair.publicKey);
|
|
if (returnBase58) {
|
|
return {
|
|
privateKey: Base58.encode(keyPair.secretKey),
|
|
publicKey: Base58.encode(keyPair.publicKey)
|
|
};
|
|
} else {
|
|
return {
|
|
privateKey: keyPair.secretKey,
|
|
publicKey: keyPair.publicKey
|
|
};
|
|
}
|
|
}
|
|
|
|
function stringtoUTF8Array(message) {
|
|
if (typeof message == 'string') {
|
|
var s = unescape(encodeURIComponent(message)); // UTF-8
|
|
message = new Uint8Array(s.length);
|
|
for (var i = 0; i < s.length; i++) {
|
|
message[i] = s.charCodeAt(i) & 0xff;
|
|
}
|
|
}
|
|
return message;
|
|
}
|
|
|
|
function int32ToBytes(word) {
|
|
var byteArray = [];
|
|
for (var b = 0; b < 32; b += 8) {
|
|
byteArray.push((word >>> (24 - b % 32)) & 0xFF);
|
|
}
|
|
return byteArray;
|
|
}
|
|
|
|
function int64ToBytes(int64) {
|
|
// we want to represent the input as a 8-bytes array
|
|
var byteArray = [0, 0, 0, 0, 0, 0, 0, 0];
|
|
|
|
for (var index = 0; index < byteArray.length; index++) {
|
|
var byte = int64 & 0xff;
|
|
byteArray[byteArray.length - index - 1] = byte;
|
|
int64 = (int64 - byte) / 256;
|
|
}
|
|
|
|
return byteArray;
|
|
}
|
|
|
|
function appendBuffer(buffer1, buffer2) {
|
|
buffer1 = new Uint8Array(buffer1);
|
|
buffer2 = new Uint8Array(buffer2);
|
|
var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
|
|
tmp.set(buffer1, 0);
|
|
tmp.set(buffer2, buffer1.byteLength);
|
|
return tmp;
|
|
}
|
|
|
|
function equal(buf1, buf2) {
|
|
if (buf1.byteLength != buf2.byteLength) return false;
|
|
var dv1 = new Uint8Array(buf1);
|
|
var dv2 = new Uint8Array(buf2);
|
|
for (var i = 0; i != buf1.byteLength; i++) {
|
|
if (dv1[i] != dv2[i]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function generateAccountSeed(seed, nonce, returnBase58) {
|
|
if (typeof (seed) == "string") {
|
|
seed = Base58.decode(seed);
|
|
}
|
|
|
|
nonceBytes = int32ToBytes(nonce);
|
|
|
|
var resultSeed = new Uint8Array();
|
|
|
|
resultSeed = appendBuffer(resultSeed, nonceBytes);
|
|
resultSeed = appendBuffer(resultSeed, seed);
|
|
resultSeed = appendBuffer(resultSeed, nonceBytes);
|
|
|
|
if (returnBase58) {
|
|
return Base58.encode(SHA256.digest(SHA256.digest(resultSeed)));
|
|
} else {
|
|
return new SHA256.digest(SHA256.digest(resultSeed));
|
|
}
|
|
|
|
}
|
|
|
|
function getAccountAddressFromPublicKey(publicKey) {
|
|
var ADDRESS_VERSION = 58; // Q
|
|
|
|
if (typeof (publicKey) == "string") {
|
|
publicKey = Base58.decode(publicKey);
|
|
}
|
|
|
|
var publicKeyHashSHA256 = SHA256.digest(publicKey);
|
|
|
|
var ripemd160 = new RIPEMD160();
|
|
|
|
var publicKeyHash = ripemd160.digest(publicKeyHashSHA256);
|
|
|
|
var addressArray = new Uint8Array();
|
|
|
|
addressArray = appendBuffer(addressArray, [ADDRESS_VERSION]);
|
|
addressArray = appendBuffer(addressArray, publicKeyHash);
|
|
|
|
var checkSum = SHA256.digest(SHA256.digest(addressArray));
|
|
|
|
addressArray = appendBuffer(addressArray, checkSum.subarray(0, 4));
|
|
|
|
return Base58.encode(addressArray);
|
|
}
|
|
|
|
function getAccountAddressType(address) {
|
|
try {
|
|
var ADDRESS_VERSION = 58; // Q
|
|
var AT_ADDRESS_VERSION = 23; // A
|
|
|
|
if (typeof (address) == "string") {
|
|
address = Base58.decode(address);
|
|
}
|
|
|
|
var checkSum = address.subarray(address.length - 4, address.length)
|
|
var addressWitoutChecksum = address.subarray(0, address.length - 4);
|
|
|
|
var checkSumTwo = SHA256.digest(SHA256.digest(addressWitoutChecksum));
|
|
checkSumTwo = checkSumTwo.subarray(0, 4);
|
|
|
|
if (equal(checkSum, checkSumTwo)) {
|
|
if (address[0] == ADDRESS_VERSION) {
|
|
return "standard";
|
|
}
|
|
if (address[0] == AT_ADDRESS_VERSION) {
|
|
return "at";
|
|
}
|
|
}
|
|
|
|
return "invalid";
|
|
|
|
} catch (e) {
|
|
return "invalid";
|
|
}
|
|
}
|
|
|
|
function isValidAddress(address) {
|
|
return (getAccountAddressType(address) != "invalid");
|
|
}
|
|
|
|
function generateSignaturePaymentTransaction(keyPair, lastReference, recipient, amount, fee, timestamp) {
|
|
const data = generatePaymentTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp);
|
|
return nacl.sign.detached(data, keyPair.privateKey);
|
|
}
|
|
|
|
function generatePaymentTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, signature) {
|
|
return appendBuffer(generatePaymentTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp),
|
|
signature);
|
|
}
|
|
|
|
function generatePaymentTransactionBase(publicKey, lastReference, recipient, amount, fee, timestamp) {
|
|
const txType = TYPES.PAYMENT_TRANSACTION;
|
|
const typeBytes = int32ToBytes(txType);
|
|
const timestampBytes = int64ToBytes(timestamp);
|
|
const amountBytes = int64ToBytes(amount * 100000000);
|
|
const feeBytes = int64ToBytes(fee * 100000000);
|
|
|
|
var data = new Uint8Array();
|
|
|
|
data = appendBuffer(data, typeBytes);
|
|
data = appendBuffer(data, timestampBytes);
|
|
data = appendBuffer(data, lastReference);
|
|
data = appendBuffer(data, publicKey);
|
|
data = appendBuffer(data, recipient);
|
|
data = appendBuffer(data, amountBytes);
|
|
data = appendBuffer(data, feeBytes);
|
|
|
|
return data;
|
|
}
|
|
|
|
function generateSignatureMessageTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted) {
|
|
const data = generateMessageTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted);
|
|
return nacl.sign.detached(data, keyPair.privateKey);
|
|
}
|
|
|
|
function generateMessageTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted, signature) {
|
|
return appendBuffer(generateMessageTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted),
|
|
signature);
|
|
}
|
|
|
|
function generateMessageTransactionBase(publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted) {
|
|
txType = TYPES.MESSAGE_TRANSACTION;
|
|
|
|
const typeBytes = int32ToBytes(txType);
|
|
const timestampBytes = int64ToBytes(timestamp);
|
|
const amountBytes = int64ToBytes(amount * 100000000);
|
|
const feeBytes = int64ToBytes(fee * 100000000);
|
|
const messageLength = int32ToBytes(message.length);
|
|
const key = int64ToBytes(0);
|
|
|
|
isTextB = new Uint8Array(1);
|
|
isTextB[0] = isText;
|
|
|
|
isEncryptedB = new Uint8Array(1);
|
|
isEncryptedB[0] = isEncrypted;
|
|
|
|
var data = new Uint8Array();
|
|
|
|
data = appendBuffer(data, typeBytes);
|
|
data = appendBuffer(data, timestampBytes);
|
|
data = appendBuffer(data, lastReference);
|
|
data = appendBuffer(data, publicKey);
|
|
data = appendBuffer(data, recipient);
|
|
data = appendBuffer(data, key);
|
|
data = appendBuffer(data, amountBytes);
|
|
data = appendBuffer(data, messageLength);
|
|
data = appendBuffer(data, message);
|
|
data = appendBuffer(data, isEncryptedB);
|
|
data = appendBuffer(data, isTextB);
|
|
data = appendBuffer(data, feeBytes);
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
function generateSignatureArbitraryTransactionV3(keyPair, lastReference, service, arbitraryData, fee, timestamp) {
|
|
const data = generateArbitraryTransactionV3Base(keyPair.publicKey, lastReference, service, arbitraryData, fee, timestamp);
|
|
return nacl.sign.detached(data, keyPair.privateKey);
|
|
}
|
|
|
|
function generateArbitraryTransactionV3(keyPair, lastReference, service, arbitraryData, fee, timestamp, signature) {
|
|
return appendBuffer(generateArbitraryTransactionV3Base(keyPair.publicKey, lastReference, service, arbitraryData, fee, timestamp),
|
|
signature);
|
|
}
|
|
|
|
function generateArbitraryTransactionV3Base(publicKey, lastReference, service, arbitraryData, fee, timestamp) {
|
|
const txType = TYPES.ARBITRARY_TRANSACTION;
|
|
const typeBytes = int32ToBytes(txType);
|
|
const timestampBytes = int64ToBytes(timestamp);
|
|
const feeBytes = int64ToBytes(fee * 100000000);
|
|
const serviceBytes = int32ToBytes(service);
|
|
const dataSizeBytes = int32ToBytes(arbitraryData.length);
|
|
const paymentsLengthBytes = int32ToBytes(0); // Support payments - not yet.
|
|
|
|
var data = new Uint8Array();
|
|
|
|
data = appendBuffer(data, typeBytes);
|
|
data = appendBuffer(data, timestampBytes);
|
|
data = appendBuffer(data, lastReference);
|
|
data = appendBuffer(data, publicKey);
|
|
data = appendBuffer(data, paymentsLengthBytes);
|
|
// Here it is necessary to insert the payments, if there are
|
|
data = appendBuffer(data, serviceBytes);
|
|
data = appendBuffer(data, dataSizeBytes);
|
|
data = appendBuffer(data, arbitraryData);
|
|
data = appendBuffer(data, feeBytes);
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
function generateSignatureRegisterNameTransaction(keyPair, lastReference, owner, name, value, fee, timestamp) {
|
|
const data = generateRegisterNameTransactionBase(keyPair.publicKey, lastReference, owner, name, value, fee, timestamp);
|
|
return nacl.sign.detached(data, keyPair.privateKey);
|
|
}
|
|
|
|
function generateRegisterNameTransaction(keyPair, lastReference, owner, name, value, fee, timestamp, signature) {
|
|
return appendBuffer(generateRegisterNameTransactionBase(keyPair.publicKey, lastReference, owner, name, value, fee, timestamp),
|
|
signature);
|
|
}
|
|
|
|
function generateRegisterNameTransactionBase(publicKey, lastReference, owner, name, value, fee, timestamp) {
|
|
const txType = TYPES.REGISTER_NAME_TRANSACTION;
|
|
const typeBytes = int32ToBytes(txType);
|
|
const timestampBytes = int64ToBytes(timestamp);
|
|
const feeBytes = int64ToBytes(fee * 100000000);
|
|
const nameSizeBytes = int32ToBytes(name.length);
|
|
const valueSizeBytes = int32ToBytes(value.length);
|
|
|
|
var data = new Uint8Array();
|
|
|
|
data = appendBuffer(data, typeBytes);
|
|
data = appendBuffer(data, timestampBytes);
|
|
data = appendBuffer(data, lastReference);
|
|
data = appendBuffer(data, publicKey);
|
|
data = appendBuffer(data, owner);
|
|
data = appendBuffer(data, nameSizeBytes);
|
|
data = appendBuffer(data, name);
|
|
data = appendBuffer(data, valueSizeBytes);
|
|
data = appendBuffer(data, value);
|
|
data = appendBuffer(data, feeBytes);
|
|
|
|
return data;
|
|
}
|