All files / src register_multisignature_account.ts

100% Statements 24/24
100% Branches 14/14
100% Functions 2/2
100% Lines 24/24

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 114 115 116 117 118 119 120                            3x           3x 3x               3x                       3x           49x         5x         44x         5x         39x 1x         38x           34x     3x     49x               34x   34x 34x   34x                       34x 17x     17x 17x   17x    
/*
 * 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 {
	isValidInteger,
	validateKeysgroup,
	validateNetworkIdentifier,
} from '@liskhq/lisk-validator';
 
import { MultisignatureTransaction } from './12_multisignature_transaction';
import {
	MULTISIGNATURE_FEE,
	MULTISIGNATURE_MAX_KEYSGROUP,
	MULTISIGNATURE_MAX_LIFETIME,
	MULTISIGNATURE_MIN_KEYSGROUP,
	MULTISIGNATURE_MIN_LIFETIME,
} from './constants';
import { TransactionJSON } from './transaction_types';
import { createBaseTransaction, prependPlusToPublicKeys } from './utils';
 
export interface RegisterMultisignatureInputs {
	readonly keysgroup: ReadonlyArray<string>;
	readonly lifetime: number;
	readonly minimum: number;
	readonly passphrase?: string;
	readonly secondPassphrase?: string;
	readonly timeOffset?: number;
	readonly networkIdentifier: string;
}
 
const validateInputs = ({
	keysgroup,
	lifetime,
	minimum,
	networkIdentifier,
}: RegisterMultisignatureInputs): void => {
	if (
		!isValidInteger(lifetime) ||
		lifetime < MULTISIGNATURE_MIN_LIFETIME ||
		lifetime > MULTISIGNATURE_MAX_LIFETIME
	) {
		throw new Error(
			`Please provide a valid lifetime value. Expected integer between ${MULTISIGNATURE_MIN_LIFETIME} and ${MULTISIGNATURE_MAX_LIFETIME}.`,
		);
	}
 
	if (
		!isValidInteger(minimum) ||
		minimum < MULTISIGNATURE_MIN_KEYSGROUP ||
		minimum > MULTISIGNATURE_MAX_KEYSGROUP
	) {
		throw new Error(
			`Please provide a valid minimum value. Expected integer between ${MULTISIGNATURE_MIN_KEYSGROUP} and ${MULTISIGNATURE_MAX_KEYSGROUP}.`,
		);
	}
 
	if (keysgroup.length < minimum) {
		throw new Error(
			'Minimum number of signatures is larger than the number of keys in the keysgroup.',
		);
	}
 
	validateKeysgroup(
		keysgroup,
		MULTISIGNATURE_MIN_KEYSGROUP,
		MULTISIGNATURE_MAX_KEYSGROUP,
	);
 
	validateNetworkIdentifier(networkIdentifier);
};
 
export const registerMultisignature = (
	inputs: RegisterMultisignatureInputs,
): Partial<TransactionJSON> => {
	validateInputs(inputs);
	const {
		keysgroup,
		lifetime,
		minimum,
		passphrase,
		secondPassphrase,
		networkIdentifier,
	} = inputs;
 
	const plusPrependedKeysgroup = prependPlusToPublicKeys(keysgroup);
	const keygroupFees = plusPrependedKeysgroup.length + 1;
 
	const transaction = {
		...createBaseTransaction(inputs),
		type: 12,
		fee: (MULTISIGNATURE_FEE * keygroupFees).toString(),
		asset: {
			min: minimum,
			lifetime,
			keysgroup: plusPrependedKeysgroup,
		},
		networkIdentifier,
	};
 
	if (!passphrase) {
		return transaction;
	}
 
	const multisignatureTransaction = new MultisignatureTransaction(transaction);
	multisignatureTransaction.sign(passphrase, secondPassphrase);
 
	return multisignatureTransaction.toJSON();
};