Skip to content

Commit

Permalink
Allow votes[] to include publicKeys and ADM addresses and delegate na…
Browse files Browse the repository at this point in the history
…mes (mixed). Exclude duplicates.
  • Loading branch information
martiliones committed Feb 11, 2022
1 parent acadab3 commit 6b7bf7d
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 15 deletions.
61 changes: 55 additions & 6 deletions groups/voteForDelegate.js
@@ -1,4 +1,5 @@
const axios = require('axios');
const get = require('./get');
const logger = require('../helpers/logger');
const keys = require('../helpers/keys');
const constants = require('../helpers/constants');
Expand All @@ -7,34 +8,82 @@ const validator = require('../helpers/validator');

const DEFAULT_VOTE_FOR_DELEGATE_RETRIES = 4; // How much re-tries for send tokens requests by default. Total 4+1 tries

const publicKeysCache = { };

module.exports = (nodeManager) => {
/**
* Creates votes for delegate transaction, signs it, and broadcasts to ADAMANT network
* See https://github.com/Adamant-im/adamant/wiki/Transaction-Types#type-3-vote-for-delegate-transaction
* @param {string} passPhrase Senders's passPhrase. Sender's address will be derived from it.
* @param {string[]} votes PublicKeys for upvote and downvote
* @param {string[]} votes PublicKeys, ADM addresses and delegate names for upvote and downvote
* @param {number} maxRetries How much times to retry request
* @returns {Promise} Request results
*/
return (passPhrase, votes, maxRetries = DEFAULT_VOTE_FOR_DELEGATE_RETRIES, retryNo = 0) => {
return async (passPhrase, votes, maxRetries = DEFAULT_VOTE_FOR_DELEGATE_RETRIES, retryNo = 0) => {

let transaction;

try {
if (!validator.validatePassPhrase(passPhrase))
return validator.badParameter('passPhrase')
return validator.badParameter('passPhrase');

const keyPair = keys.createKeypairFromPassPhrase(passPhrase);

if (!validator.validateAdmVotes(votes))
return validator.badParameter('votes')
const uniqueVotes = [];

for (let i = votes.length - 1; i >= 0; i--) {
const vote = votes[i];
const voteName = vote.slice(1);
const voteDirection = vote.charAt(0);

const cachedPublicKey = publicKeysCache[voteName];

if (cachedPublicKey) {
votes[i] = `${voteDirection}${cachedPublicKey}`;
continue;
}

if (validator.validateAdmVoteForAddress(vote)) {
const res = await get(nodeManager)('/accounts', { address: voteName });

if (res.success) {
const publicKey = res.data.account.publicKey;
votes[i] = `${voteDirection}${publicKey}`;
console.log(publicKey);
publicKeysCache[voteName] = publicKey;
} else {
logger.warn(`[ADAMANT js-api] Failed to get public key for ${vote}. ${res.errorMessage}.`);
return validator.badParameter('votes')
}
} else if (validator.validateAdmVoteForDelegateName(vote)) {
const res = await get(nodeManager)('/delegates/get', { username: voteName });

if (res.success) {
const publicKey = res.data.delegate.publicKey;
votes[i] = `${voteDirection}${publicKey}`;
publicKeysCache[voteName] = publicKey;
} else {
logger.warn(`[ADAMANT js-api] Failed to get public key for ${vote}. ${res.errorMessage}.`);
return validator.badParameter('votes')
}
} else if (!validator.validateAdmVoteForPublicKey(vote)) {
return validator.badParameter('votes')
}

// Exclude duplicates
const foundCopy = uniqueVotes.findIndex((v) => v.slice(1) === votes[i].slice(1));

if (foundCopy === -1) {
uniqueVotes.push(votes[i]);
}
}

const type = constants.transactionTypes.VOTE;

const data = {
type,
keyPair,
votes,
votes: uniqueVotes,
};

transaction = transactionFormer.createTransaction(type, data);
Expand Down
6 changes: 4 additions & 2 deletions helpers/constants.js
Expand Up @@ -31,8 +31,10 @@ module.exports = {
RE_HEX: /^[a-fA-F0-9]+$/,
RE_BASE64: /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/,
RE_ADM_ADDRESS: /^U([0-9]{6,})$/,
RE_ADM_VOTE: /^(\+|-)[a-fA-F0-9]{64}$/,
RE_ADM_DELEGATE_NAME: /^[a-z0-9!@$&_]{1,20}*$/,
RE_ADM_VOTE_FOR_PUBLIC_KEY: /^(\+|-)[a-fA-F0-9]{64}$/,
RE_ADM_VOTE_FOR_ADDRESS: /^(\+|-)U([0-9]{6,})$/,
RE_ADM_VOTE_FOR_DELEGATE_NAME: /^(\+|-)([a-z0-9!@$&_]{1,20})$/,
RE_ADM_DELEGATE_NAME: /^[a-z0-9!@$&_]{1,20}$/,
RE_BTC_ADDRESS: /^(bc1|[13])[a-km-zA-HJ-NP-Z02-9]{25,39}$/,
RE_DASH_ADDRESS: /^[7X][1-9A-HJ-NP-Za-km-z]{33,}$/,
RE_DOGE_ADDRESS: /^[A|D|9][A-Z0-9]([0-9a-zA-Z]{9,})$/,
Expand Down
24 changes: 17 additions & 7 deletions helpers/validator.js
Expand Up @@ -52,15 +52,25 @@ module.exports = {
return true
},

validateAdmVotes(publicKeys) {
for (let i = publicKeys.length - 1; i >= 0; i--) {
const publicKey = publicKeys[i];
validateAdmVoteForPublicKey(publicKey) {
if (!publicKey || typeof(publicKey) !== 'string' || !constants.RE_ADM_VOTE_FOR_PUBLIC_KEY.test(publicKey))
return false
else
return true
},

if (!publicKey || typeof(publicKey) !== 'string' || !constants.RE_ADM_VOTE.test(publicKey))
return false
}
validateAdmVoteForAddress(address) {
if (!address || typeof(address) !== 'string' || !constants.RE_ADM_VOTE_FOR_ADDRESS.test(address))
return false
else
return true
},

return true
validateAdmVoteForDelegateName(delegateName) {
if (!delegateName || typeof(delegateName) !== 'string' || !constants.RE_ADM_VOTE_FOR_DELEGATE_NAME.test(delegateName))
return false
else
return true
},

validateIntegerAmount(amount) {
Expand Down

0 comments on commit 6b7bf7d

Please sign in to comment.