Source: facade/NemFacade.js

const { Hash256, PrivateKey } = require('../CryptoTypes');
const { NetworkLocator } = require('../Network');
const { KeyPair, Verifier } = require('../nem/KeyPair');
const { Address, Network } = require('../nem/Network');
const { TransactionFactory } = require('../nem/TransactionFactory');
const { keccak_256 } = require('js-sha3');

/**
 * Facade used to interact with NEM blockchain.
 */
class NemFacade {
	static BIP32_COIN_ID = 43;

	static BIP32_CURVE_NAME = 'ed25519-keccak';

	static Address = Address;

	static KeyPair = KeyPair;

	static Verifier = Verifier;

	/**
	 * Creates a NEM facade.
	 * @param {string} nemNetworkName NEM network name.
	 */
	constructor(nemNetworkName) {
		this.network = NetworkLocator.findByName(Network.NETWORKS, nemNetworkName);
		this.transactionFactory = new TransactionFactory(this.network);
	}

	// the following three functions are NOT static in order for NemFacade and SymbolFacade to conform to the same interface

	/**
	 * Hashes a NEM transaction.
	 * @param {object} transaction Transaction object.
	 * @returns {Hash256} Transaction hash.
	 */
	hashTransaction(transaction) { // eslint-disable-line class-methods-use-this
		const nonVerifiableTransaction = TransactionFactory.toNonVerifiableTransaction(transaction);
		return new Hash256(new Uint8Array(keccak_256.create().update(nonVerifiableTransaction.serialize()).arrayBuffer()));
	}

	/**
	 * Signs a NEM transaction.
	 * @param {KeyPair} keyPair Key pair.
	 * @param {object} transaction Transaction object.
	 * @returns {Signature} Transaction signature.
	 */
	signTransaction(keyPair, transaction) { // eslint-disable-line class-methods-use-this
		const nonVerifiableTransaction = TransactionFactory.toNonVerifiableTransaction(transaction);
		return keyPair.sign(nonVerifiableTransaction.serialize());
	}

	/**
	 * Verifies a NEM transaction.
	 * @param {object} transaction Transaction object.
	 * @param {Signature} signature Signature to verify.
	 * @returns {boolean} true if transaction signature is verified.
	 */
	verifyTransaction(transaction, signature) { // eslint-disable-line class-methods-use-this
		const nonVerifiableTransaction = TransactionFactory.toNonVerifiableTransaction(transaction);
		return new Verifier(transaction.signerPublicKey).verify(nonVerifiableTransaction.serialize(), signature);
	}

	/**
	 * Derives a NEM KeyPair from a BIP32 node.
	 * @param {Bip32Node} bip32Node BIP32 node.
	 * @returns {KeyPair} Derived key pair.
	 */
	static bip32NodeToKeyPair(bip32Node) {
		// BIP32 private keys should be used as is, so reverse here to counteract reverse in KeyPair
		const reversedPrivateKeyBytes = new Uint8Array([...bip32Node.privateKey.bytes]);
		reversedPrivateKeyBytes.reverse();

		return new KeyPair(new PrivateKey(reversedPrivateKeyBytes));
	}
}

module.exports = { NemFacade };