nem-voting
Version:
380 lines • 15.9 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const nem_library_1 = require("nem-library");
const CryptoJS = require("crypto-js");
const rxjs_1 = require("rxjs");
let accountHttp;
let chainHttp;
let blockHttp;
let transactionHttp;
const testNodeAddress = "hugetestalice.nem.ninja";
exports.testNodeAddress = testNodeAddress;
const mainNodeAddress = "hugealice.nem.ninja";
exports.mainNodeAddress = mainNodeAddress;
const initializeHttp = () => {
let nodes = [];
if (nem_library_1.NEMLibrary.getNetworkType() === nem_library_1.NetworkTypes.TEST_NET) {
nodes = [
{ protocol: "http", domain: testNodeAddress, port: 7890 },
];
}
else if (nem_library_1.NEMLibrary.getNetworkType() === nem_library_1.NetworkTypes.MAIN_NET) {
nodes = [
{ protocol: "http", domain: mainNodeAddress, port: 7890 },
];
}
else {
throw new Error("Not bootstrapped");
}
accountHttp = new nem_library_1.AccountHttp(nodes);
if (nem_library_1.NEMLibrary.getNetworkType() === nem_library_1.NetworkTypes.TEST_NET) {
accountHttp.historicalNodes = [
{ protocol: "http", domain: testNodeAddress, port: 7890 },
];
}
if (nem_library_1.NEMLibrary.getNetworkType() === nem_library_1.NetworkTypes.MAIN_NET) {
accountHttp.historicalNodes = [
{ protocol: "http", domain: mainNodeAddress, port: 7890 },
];
}
chainHttp = new nem_library_1.ChainHttp(nodes);
blockHttp = new nem_library_1.BlockHttp(nodes);
transactionHttp = new nem_library_1.TransactionHttp(nodes);
};
const getTransferTransaction = (transaction) => {
if (transaction.type === nem_library_1.TransactionTypes.MULTISIG) {
return transaction.otherTransaction;
}
else if (transaction.type === nem_library_1.TransactionTypes.TRANSFER) {
return transaction;
}
return null;
};
exports.getTransferTransaction = getTransferTransaction;
const getTransactionPageable = (receiver, pageSize) => {
initializeHttp();
return accountHttp.incomingTransactionsPaginated(receiver, { pageSize });
};
exports.getTransactionPageable = getTransactionPageable;
const getAllTransactions = (receiver) => {
initializeHttp();
const pageable = accountHttp.incomingTransactionsPaginated(receiver, { pageSize: 100 });
return pageable
.map((allTransactions) => {
pageable.nextPage();
return allTransactions.filter((t) => (t.type === nem_library_1.TransactionTypes.MULTISIG || t.type === nem_library_1.TransactionTypes.TRANSFER));
}).reduce((acc, page) => {
return acc.concat(page);
}, []);
};
exports.getAllTransactions = getAllTransactions;
const getAllOutgoingTransactions = (sender) => {
initializeHttp();
const pageable = accountHttp.outgoingTransactionsPaginated(sender, { pageSize: 100 });
return pageable
.map((allTransactions) => {
pageable.nextPage();
return allTransactions.filter((t) => (t.type === nem_library_1.TransactionTypes.MULTISIG || t.type === nem_library_1.TransactionTypes.TRANSFER));
}).reduce((acc, page) => {
return acc.concat(page);
}, []);
};
const getOutgoingTransactionsWithString = (queryString, sender, position = 0) => {
initializeHttp();
return getAllOutgoingTransactions(sender)
.map((allTransactions) => {
// We only want transfer and multisig transactions, and we are only interested in
// the inner transaction for multisig transactions
const transactions = allTransactions
.map((transaction) => {
if (transaction.type === nem_library_1.TransactionTypes.MULTISIG) {
transaction = transaction.otherTransaction;
}
return transaction;
});
// Then we get the messages, we only want the plain messages, not encrypted
return transactions
.filter((t) => t.message.isPlain())
.filter((t) => t.message.plain().includes(queryString, position));
});
};
exports.getOutgoingTransactionsWithString = getOutgoingTransactionsWithString;
const getPageOfTransactions = (address, pageSize, lastId) => {
initializeHttp();
return accountHttp.incomingTransactions(address, {
pageSize,
id: lastId,
})
.map((allTransactions) => {
return allTransactions.filter((t) => (t.type === nem_library_1.TransactionTypes.MULTISIG || t.type === nem_library_1.TransactionTypes.TRANSFER));
}).reduce((acc, page) => {
return acc.concat(page);
}, []);
};
const getPageOfTransactionsWithString = (address, pageSize, queryString, lastId, sender, position = 0) => {
return getPageOfTransactions(address, pageSize, lastId)
.map((allTransactions) => {
// We only want transfer and multisig transactions, and we are only interested in
// the inner transaction for multisig transactions
let transactions = allTransactions
.filter((t) => (t.type === nem_library_1.TransactionTypes.MULTISIG || t.type === nem_library_1.TransactionTypes.TRANSFER))
.map((transaction) => {
if (transaction.type === nem_library_1.TransactionTypes.MULTISIG) {
transaction = transaction.otherTransaction;
}
return transaction;
});
// filter by sender
if (sender !== undefined) {
transactions = transactions.filter((t) => (t.signer !== undefined && t.signer.address.plain() === sender.plain()));
}
// Then we get the messages, we only want the plain messages, not encrypted
return transactions
.filter((t) => t.message.isPlain())
.filter((t) => t.message.plain().includes(queryString, position));
});
};
exports.getPageOfTransactionsWithString = getPageOfTransactionsWithString;
const findTransaction = (sender, receiver) => {
return getAllTransactions(receiver)
.map((transactions) => {
const filtered = transactions.filter((transaction) => {
const tt = getTransferTransaction(transaction);
if (!tt) {
return false;
}
return (tt.signer.address.plain() === sender.plain());
});
if (filtered.length === 0) {
return null;
}
else {
return filtered[0];
}
});
};
exports.findTransaction = findTransaction;
const getTransactionsWithString = (queryString, receiver, sender, position = 0) => {
initializeHttp();
return getAllTransactions(receiver)
.map((allTransactions) => {
// We only want transfer and multisig transactions, and we are only interested in
// the inner transaction for multisig transactions
let transactions = allTransactions
.filter((t) => (t.type === nem_library_1.TransactionTypes.MULTISIG || t.type === nem_library_1.TransactionTypes.TRANSFER))
.map((transaction) => {
if (transaction.type === nem_library_1.TransactionTypes.MULTISIG) {
transaction = transaction.otherTransaction;
}
return transaction;
});
// filter by sender
if (sender !== undefined) {
transactions = transactions.filter((t) => (t.signer !== undefined && t.signer.address.plain() === sender.plain()));
}
// Then we get the messages, we only want the plain messages, not encrypted
return transactions
.filter((t) => t.message.isPlain())
.filter((t) => t.message.plain().includes(queryString, position));
});
};
exports.getTransactionsWithString = getTransactionsWithString;
const getFirstMessageWithString = (queryString, receiver, sender, position = 0) => {
return getTransactionsWithString(queryString, receiver, sender = sender, position = position)
.map((transactions) => {
if (transactions.length === 0) {
return null;
}
return transactions[transactions.length - 1].message.plain();
});
};
exports.getFirstMessageWithString = getFirstMessageWithString;
// Gets the address of the first person that sent a transaction to this address
const getFirstSender = (receiver) => {
return getTransactionsWithString("", receiver)
.map((transactions) => {
transactions = transactions.sort((a, b) => {
return a.getTransactionInfo().height - b.getTransactionInfo().height;
});
if (!transactions || transactions.length === 0 || !transactions[0].signer) {
return null;
}
else {
return transactions[0].signer.address;
}
});
};
exports.getFirstSender = getFirstSender;
const getAllMessagesWithString = (queryString, receiver, sender, block) => {
return getTransactionsWithString(queryString, receiver, sender = sender)
.map((transactions) => {
if (transactions.length === 0) {
return null;
}
// filter only transactions sent before block
if (block !== undefined) {
const validTransactions = transactions.filter((t) => t.getTransactionInfo().height < block);
return validTransactions.map((transaction) => transaction.message.plain());
}
else {
return transactions.map((transaction) => transaction.message.plain());
}
});
};
exports.getAllMessagesWithString = getAllMessagesWithString;
const NEM_EPOCH = Date.UTC(2015, 2, 29, 0, 6, 25, 0);
/**
* Create a time stamp for a NEM transaction from a given timestamp
*
* @param {number} - javascript timestamp in ms
*
* @return {number} - The NEM transaction time stamp in milliseconds
*/
const toNEMTimeStamp = (date) => {
const ts = Math.floor((date / 1000) - (NEM_EPOCH.valueOf() / 1000));
return ts;
};
const getBlockchainHeight = () => {
initializeHttp();
return chainHttp.getBlockchainHeight().first().toPromise();
};
const getBlockByHeight = (height) => {
initializeHttp();
return blockHttp.getBlockByHeight(height).first().toPromise();
};
const getLastBlock = () => {
initializeHttp();
return chainHttp.getBlockchainLastBlock().first().toPromise();
};
/**
* getHeightByTimestamp(timestamp) returns the last harvested block at the time of the timestamp.
*
* @param {integer} timestamp - javascript timestamp in ms
*
* @return {promise} - a promise that returns the block height
*/
const getHeightByTimestampPromise = (timestamp) => __awaiter(this, void 0, void 0, function* () {
try {
// Approximate (60s average block time)
const nemTimestamp = toNEMTimeStamp(timestamp);
const now = toNEMTimeStamp(Date.now());
// const curHeight = await getBlockchainHeight();
const curHeight = yield getBlockchainHeight();
// memoization
const memo = [];
let foundHeight = null;
let lastTimestamp = now;
let lastHeight = curHeight;
let lb = 1; // lower bound
let ub = curHeight; // upper bound
// estimation
while (foundHeight === null) {
if (lb === ub) {
return lb;
}
let height = lastHeight + Math.ceil((nemTimestamp - lastTimestamp) / 60);
if (height < lb) {
height = lb;
}
else if (height > ub) {
height = ub;
}
const block = (memo[height]) ? memo[height] : yield getBlockByHeight(height);
memo[height] = block;
if (block.timeStamp <= nemTimestamp) {
const nextBlock = (memo[height + 1]) ? memo[height + 1] : yield getBlockByHeight(height + 1);
memo[height + 1] = nextBlock;
// check if target
if (nextBlock.timeStamp > nemTimestamp) {
foundHeight = height;
}
else {
lb = height + 1;
}
}
else {
ub = height - 1;
}
lastHeight = height;
lastTimestamp = block.timeStamp;
}
return foundHeight;
}
catch (err) {
throw err;
}
});
exports.getHeightByTimestampPromise = getHeightByTimestampPromise;
const getHeightByTimestamp = (timestamp) => {
return rxjs_1.Observable.fromPromise(getHeightByTimestampPromise(timestamp));
};
exports.getHeightByTimestamp = getHeightByTimestamp;
const getImportances = (addresses, block) => {
initializeHttp();
if (block === undefined || block < 0) {
return accountHttp.getBatchAccountData(addresses)
.map((accountsData) => {
return accountsData.map((account) => {
return account.importance;
});
});
}
else {
return accountHttp.getBatchHistoricalAccountData(addresses, block, block, 1)
.map((accountsHistoricalInfo) => {
return accountsHistoricalInfo.map((accountInfo) => {
return accountInfo[0].importance;
});
});
}
};
exports.getImportances = getImportances;
const getMessageTransaction = (message, address) => {
const transferTransaction = nem_library_1.TransferTransaction.create(nem_library_1.TimeWindow.createWithDeadline(), address, new nem_library_1.XEM(0), nem_library_1.PlainMessage.create(message));
return transferTransaction;
};
exports.getMessageTransaction = getMessageTransaction;
const getMultisigMessage = (multisigAccount, message, address) => {
const transferTransaction = nem_library_1.TransferTransaction.create(nem_library_1.TimeWindow.createWithDeadline(1), address, new nem_library_1.XEM(0), nem_library_1.PlainMessage.create(message));
const multisigTransaction = nem_library_1.MultisigTransaction.create(nem_library_1.TimeWindow.createWithDeadline(), transferTransaction, multisigAccount);
return multisigTransaction;
};
exports.getMultisigMessage = getMultisigMessage;
const publicKeyToAddress = (pubKey) => {
if (pubKey[0] >= "8") {
pubKey = "00" + pubKey;
}
const pa = nem_library_1.PublicAccount.createWithPublicKey(pubKey);
return pa.address;
};
// Poll Address from index information and creator
const generatePollAddress = (title, publicKey) => {
const pk = CryptoJS.SHA3(publicKey + title, { outputLength: 256 }).toString();
const pa = nem_library_1.PublicAccount.createWithPublicKey(pk);
return pa.address;
};
exports.generatePollAddress = generatePollAddress;
const deriveOptionAddress = (pollAddress, option) => {
const plainAddress = pollAddress.plain();
const pubKey = CryptoJS.SHA3(plainAddress + option, { outputLength: 256 }).toString();
return publicKeyToAddress(pubKey);
};
exports.deriveOptionAddress = deriveOptionAddress;
const generateRandomAddress = () => {
const pk = CryptoJS.lib.WordArray.random(32).toString();
return publicKeyToAddress(pk);
};
exports.generateRandomAddress = generateRandomAddress;
const generateRandomPubKey = () => {
return CryptoJS.lib.WordArray.random(32).toString();
};
exports.generateRandomPubKey = generateRandomPubKey;
//# sourceMappingURL=utils.js.map