All files / src cast_votes.ts

100% Statements 25/25
100% Branches 10/10
100% Functions 2/2
100% Lines 25/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113                            3x 3x         3x   3x                                         3x         38x 2x       36x 2x         34x   29x     3x 38x             29x   29x 29x 29x         29x                   29x 8x     21x 21x                     21x 21x   21x    
/*
 * Copyright © 2019 Lisk Foundation
 *
 * See the LICENSE file at the top-level directory of this distribution
 * for licensing information.
 *
 * Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation,
 * no part of this software, including this file, may be copied, modified,
 * propagated, or distributed except according to the terms contained in the
 * LICENSE file.
 *
 * Removal or modification of this copyright notice is prohibited.
 *
 */
import { getAddressFromPassphrase } from '@liskhq/lisk-cryptography';
import {
	validateNetworkIdentifier,
	validatePublicKeys,
} from '@liskhq/lisk-validator';
 
import { VoteTransaction } from './11_vote_transaction';
import { TransactionJSON } from './transaction_types';
import {
	createBaseTransaction,
	prependMinusToPublicKeys,
	prependPlusToPublicKeys,
} from './utils';
 
export interface CastVoteInputs {
	readonly networkIdentifier: string;
	readonly passphrase?: string;
	readonly secondPassphrase?: string;
	readonly timeOffset?: number;
	readonly unvotes?: ReadonlyArray<string>;
	readonly votes?: ReadonlyArray<string>;
}
 
interface VotesObject {
	readonly unvotes?: ReadonlyArray<string>;
	readonly votes?: ReadonlyArray<string>;
	readonly networkIdentifier: string;
}
 
const validateInputs = ({
	votes = [],
	unvotes = [],
	networkIdentifier,
}: VotesObject): void => {
	if (!Array.isArray(votes)) {
		throw new Error(
			'Please provide a valid votes value. Expected an array if present.',
		);
	}
	if (!Array.isArray(unvotes)) {
		throw new Error(
			'Please provide a valid unvotes value. Expected an array if present.',
		);
	}
 
	validatePublicKeys([...votes, ...unvotes]);
 
	validateNetworkIdentifier(networkIdentifier);
};
 
export const castVotes = (inputs: CastVoteInputs): Partial<TransactionJSON> => {
	validateInputs(inputs);
	const {
		networkIdentifier,
		passphrase,
		secondPassphrase,
		votes = [],
		unvotes = [],
	} = inputs;
 
	const plusPrependedVotes = prependPlusToPublicKeys(votes);
	const minusPrependedUnvotes = prependMinusToPublicKeys(unvotes);
	const allVotes: ReadonlyArray<string> = [
		...plusPrependedVotes,
		...minusPrependedUnvotes,
	];
 
	const transaction = {
		...createBaseTransaction(inputs),
		type: 11,
		asset: {
			// TODO: Remove this after hardfork change. Amount is kept as asset property for exceptions
			amount: '0',
			votes: allVotes,
		},
	};
 
	if (!passphrase) {
		return transaction;
	}
 
	const recipientId = getAddressFromPassphrase(passphrase);
	const transactionWithSenderInfo = {
		...transaction,
		// SenderId and SenderPublicKey are expected to be exist from base transaction
		senderPublicKey: transaction.senderPublicKey as string,
		asset: {
			...transaction.asset,
			recipientId,
		},
		networkIdentifier,
	};
 
	const voteTransaction = new VoteTransaction(transactionWithSenderInfo);
	voteTransaction.sign(passphrase, secondPassphrase);
 
	return voteTransaction.toJSON();
};