import {
Address,
/* eslint-disable no-unused-vars */
Network
/* eslint-enable no-unused-vars */
} from './Network.js';
import { generateMosaicId, generateNamespaceId } from './idGenerator.js';
import * as sc from './models.js';
import {
Hash256,
PublicKey,
/* eslint-disable no-unused-vars */
Signature
/* eslint-enable no-unused-vars */
} from '../CryptoTypes.js';
import RuleBasedTransactionFactory from '../RuleBasedTransactionFactory.js';
import { uint8ToHex } from '../utils/converter.js';
/**
* Factory for creating Symbol transactions.
*/
export default class TransactionFactory {
/**
* Creates a factory for the specified network.
* @param {Network} network Symbol network.
* @param {Map<string, function>|undefined} typeRuleOverrides Type rule overrides.
*/
constructor(network, typeRuleOverrides = undefined) {
/**
* @private
*/
this._factory = TransactionFactory._buildRules(typeRuleOverrides); // eslint-disable-line no-underscore-dangle
/**
* @private
*/
this._network = network;
}
/**
* Gets rule names with registered hints.
*/
get ruleNames() {
return Array.from(this._factory.rules.keys());
}
/**
* Looks up the friendly name for the specified transaction.
* @param {sc.TransactionType} transactionType Transaction type.
* @param {number} transactionVersion Transaction version.
* @returns {string} Transaction friendly name.
*/
static lookupTransactionName(transactionType, transactionVersion) {
return `${sc.TransactionType.valueToKey(transactionType.value).toLowerCase()}_transaction_v${transactionVersion}`;
}
/**
* Creates a transaction from a transaction descriptor.
* @template TTransaction
* @param {object} transactionDescriptor Transaction descriptor.
* @param {boolean} autosort When set (default), descriptor arrays requiring ordering will be automatically sorted.
* When unset, descriptor arrays will be presumed to be already sorted.
* @param {{createByName: function}} FactoryClass Factory class used to create the transaction.
* @returns {TTransaction} Newly created transaction.
* @private
*/
_createAndExtend(transactionDescriptor, autosort, FactoryClass) {
const transaction = this._factory.createFromFactory(FactoryClass.createByName, {
...transactionDescriptor,
network: this._network.identifier
});
if (autosort)
transaction.sort();
// autogenerate artifact ids
if (sc.TransactionType.NAMESPACE_REGISTRATION === transaction.type) {
const parentId = sc.NamespaceRegistrationType.CHILD === transaction.registrationType ? transaction.parentId.value : 0n;
const rawNamespaceId = generateNamespaceId(new TextDecoder().decode(transaction.name), parentId);
transaction.id = new sc.NamespaceId(rawNamespaceId);
} else if (sc.TransactionType.MOSAIC_DEFINITION === transaction.type) {
const address = this._network.publicKeyToAddress(new PublicKey(transaction.signerPublicKey.bytes));
transaction.id = new sc.MosaicId(generateMosaicId(address, transaction.nonce.value));
}
return transaction;
}
/**
* Creates a transaction from a transaction descriptor.
* @param {object} transactionDescriptor Transaction descriptor.
* @param {boolean} autosort When set (default), descriptor arrays requiring ordering will be automatically sorted.
* When unset, descriptor arrays will be presumed to be already sorted.
* @returns {sc.Transaction} Newly created transaction.
*/
create(transactionDescriptor, autosort = true) {
return this._createAndExtend(transactionDescriptor, autosort, sc.TransactionFactory);
}
/**
* Creates an embedded transaction from a transaction descriptor.
* @param {object} transactionDescriptor Transaction descriptor.
* @param {boolean} autosort When set (default), descriptor arrays requiring ordering will be automatically sorted.
* When unset, descriptor arrays will be presumed to be already sorted.
* @returns {sc.EmbeddedTransaction} Newly created transaction.
*/
createEmbedded(transactionDescriptor, autosort = true) {
return this._createAndExtend(transactionDescriptor, autosort, sc.EmbeddedTransactionFactory);
}
/**
* Attaches a signature to a transaction.
* @param {sc.Transaction} transaction Transaction object.
* @param {Signature} signature Signature to attach.
* @returns {string} JSON transaction payload.
*/
static attachSignature(transaction, signature) {
transaction.signature = new sc.Signature(signature.bytes);
const transactionBuffer = transaction.serialize();
const hexPayload = uint8ToHex(transactionBuffer);
const jsonPayload = `{"payload": "${hexPayload}"}`;
return jsonPayload;
}
/**
* Tries to coerce an sdk type to a model type.
* @param {object} value Value to convert.
* @returns {sc.Address|undefined} Converted value or undefined.
* @private
*/
static _symbolTypeConverter(value) {
if (value instanceof Address)
return new sc.UnresolvedAddress(value.bytes);
return undefined;
}
/**
* Builds a rule based transaction factory.
* @param {Map<string, function>|undefined} typeRuleOverrides Type rule overrides.
* @returns {RuleBasedTransactionFactory} Rule based transaction factory.
* @private
*/
static _buildRules(typeRuleOverrides) {
const factory = new RuleBasedTransactionFactory(sc, this._symbolTypeConverter, typeRuleOverrides);
factory.autodetect();
['MosaicFlags', 'AccountRestrictionFlags'].forEach(name => { factory.addFlagsParser(name); });
[
'AliasAction', 'LinkAction', 'LockHashAlgorithm',
'MosaicRestrictionType', 'MosaicSupplyChangeAction',
'NamespaceRegistrationType', 'NetworkType', 'TransactionType'
].forEach(name => { factory.addEnumParser(name); });
factory.addStructParser('UnresolvedMosaic');
const sdkTypeMapping = {
UnresolvedAddress: Address,
Address,
Hash256,
PublicKey,
VotingPublicKey: PublicKey
};
Object.keys(sdkTypeMapping).forEach(name => { factory.addPodParser(name, sdkTypeMapping[name]); });
['UnresolvedMosaicId', 'TransactionType', 'UnresolvedAddress', 'struct:UnresolvedMosaic'].forEach(name => {
factory.addArrayParser(name);
});
return factory;
}
}