UNPKG

@hiero-ledger/sdk

Version:
680 lines (597 loc) 19.4 kB
// SPDX-License-Identifier: Apache-2.0 import Hbar from "../Hbar.js"; import AccountId from "../account/AccountId.js"; import FileId from "../file/FileId.js"; import ContractFunctionParameters from "./ContractFunctionParameters.js"; import Transaction, { DEFAULT_AUTO_RENEW_PERIOD, TRANSACTION_REGISTRY, } from "../transaction/Transaction.js"; import Long from "long"; import Duration from "../Duration.js"; import Key from "../Key.js"; /** * @namespace proto * @typedef {import("@hashgraph/proto").proto.ITransaction} HieroProto.proto.ITransaction * @typedef {import("@hashgraph/proto").proto.ISignedTransaction} HieroProto.proto.ISignedTransaction * @typedef {import("@hashgraph/proto").proto.TransactionBody} HieroProto.proto.TransactionBody * @typedef {import("@hashgraph/proto").proto.ITransactionBody} HieroProto.proto.ITransactionBody * @typedef {import("@hashgraph/proto").proto.ITransactionResponse} HieroProto.proto.ITransactionResponse * @typedef {import("@hashgraph/proto").proto.IContractCreateTransactionBody} HieroProto.proto.IContractCreateTransactionBody * @typedef {import("@hashgraph/proto").proto.IAccountID} HieroProto.proto.IAccountID * @typedef {import("@hashgraph/proto").proto.IFileID} HieroProto.proto.IFileID */ /** * @typedef {import("bignumber.js").default} BigNumber * @typedef {import("../channel/Channel.js").default} Channel * @typedef {import("../client/Client.js").default<*, *>} Client * @typedef {import("../transaction/TransactionId.js").default} TransactionId */ /** * Create a new smart contract. * * If this transaction succeeds, the `ContractID` for the new smart contract * SHALL be set in the transaction receipt.<br/> * The contract is defined by the initial bytecode (or `initcode`). The * `initcode` SHALL be stored either in a previously created file, or in the * transaction body itself for very small contracts. * * As part of contract creation, the constructor defined for the new smart * contract SHALL run with the parameters provided in the * `constructorParameters` field.<br/> * The gas to "power" that constructor MUST be provided via the `gas` field, * and SHALL be charged to the payer for this transaction.<br/> * If the contract _constructor_ stores information, it is charged gas for that * storage. There is a separate fee in HBAR to maintain that storage until the * expiration, and that fee SHALL be added to this transaction as part of the * _transaction fee_, rather than gas. * */ export default class ContractCreateTransaction extends Transaction { /** * @param {object} [props] * @param {FileId | string} [props.bytecodeFileId] * @param {Uint8Array} [props.bytecode] * @param {Key} [props.adminKey] * @param {number | Long} [props.gas] * @param {number | string | Long | BigNumber | Hbar} [props.initialBalance] * @param {AccountId | string} [props.proxyAccountId] * @param {Duration | Long | number} [props.autoRenewPeriod] * @param {Uint8Array} [props.constructorParameters] * @param {string} [props.contractMemo] * @param {number} [props.maxAutomaticTokenAssociations] * @param {AccountId | string} [props.stakedAccountId] * @param {Long | number} [props.stakedNodeId] * @param {boolean} [props.declineStakingReward] * @param {AccountId} [props.autoRenewAccountId] */ constructor(props = {}) { super(); /** * @private * @type {?FileId} */ this._bytecodeFileId = null; /** * @private * @type {?Uint8Array} */ this._bytecode = null; /** * @private * @type {?Key} */ this._adminKey = null; /** * @private * @type {?Long} */ this._gas = null; /** * @private * @type {?Hbar} */ this._initialBalance = null; /** * @private * @type {?AccountId} */ this._proxyAccountId = null; /** * @private * @type {Duration} */ this._autoRenewPeriod = new Duration(DEFAULT_AUTO_RENEW_PERIOD); /** * @private * @type {?Uint8Array} */ this._constructorParameters = null; /** * @private * @type {?string} */ this._contractMemo = null; /** * @private * @type {?number} */ this._maxAutomaticTokenAssociations = null; this._defaultMaxTransactionFee = new Hbar(20); /** * @private * @type {?AccountId} */ this._stakedAccountId = null; /** * @private * @type {?Long} */ this._stakedNodeId = null; /** * @private * @type {boolean} */ this._declineStakingReward = false; /** * @type {?AccountId} */ this._autoRenewAccountId = null; if (props.bytecodeFileId != null) { this.setBytecodeFileId(props.bytecodeFileId); } if (props.bytecode != null) { this.setBytecode(props.bytecode); } if (props.adminKey != null) { this.setAdminKey(props.adminKey); } if (props.gas != null) { this.setGas(props.gas); } if (props.initialBalance != null) { this.setInitialBalance(props.initialBalance); } if (props.proxyAccountId != null) { // eslint-disable-next-line deprecation/deprecation this.setProxyAccountId(props.proxyAccountId); } if (props.autoRenewPeriod != null) { this.setAutoRenewPeriod(props.autoRenewPeriod); } if (props.constructorParameters != null) { this.setConstructorParameters(props.constructorParameters); } if (props.contractMemo != null) { this.setContractMemo(props.contractMemo); } if (props.maxAutomaticTokenAssociations != null) { this.setMaxAutomaticTokenAssociations( props.maxAutomaticTokenAssociations, ); } if (props.stakedAccountId != null) { this.setStakedAccountId(props.stakedAccountId); } if (props.stakedNodeId != null) { this.setStakedNodeId(props.stakedNodeId); } if (props.declineStakingReward != null) { this.setDeclineStakingReward(props.declineStakingReward); } if (props.autoRenewAccountId != null) { this.setAutoRenewAccountId(props.autoRenewAccountId); } } /** * @internal * @param {HieroProto.proto.ITransaction[]} transactions * @param {HieroProto.proto.ISignedTransaction[]} signedTransactions * @param {TransactionId[]} transactionIds * @param {AccountId[]} nodeIds * @param {HieroProto.proto.ITransactionBody[]} bodies * @returns {ContractCreateTransaction} */ static _fromProtobuf( transactions, signedTransactions, transactionIds, nodeIds, bodies, ) { const body = bodies[0]; const create = /** @type {HieroProto.proto.IContractCreateTransactionBody} */ ( body.contractCreateInstance ); return Transaction._fromProtobufTransactions( new ContractCreateTransaction({ bytecodeFileId: create.fileID != null ? FileId._fromProtobuf( /** @type {HieroProto.proto.IFileID} */ ( create.fileID ), ) : undefined, adminKey: create.adminKey != null ? Key._fromProtobufKey(create.adminKey) : undefined, gas: create.gas != null ? create.gas : undefined, initialBalance: create.initialBalance != null ? Hbar.fromTinybars(create.initialBalance) : undefined, proxyAccountId: create.proxyAccountID != null ? AccountId._fromProtobuf( /** @type {HieroProto.proto.IAccountID} */ ( create.proxyAccountID ), ) : undefined, autoRenewPeriod: create.autoRenewPeriod != null ? create.autoRenewPeriod.seconds != null ? create.autoRenewPeriod.seconds : undefined : undefined, constructorParameters: create.constructorParameters != null ? create.constructorParameters : undefined, contractMemo: create.memo != null ? create.memo : undefined, maxAutomaticTokenAssociations: create.maxAutomaticTokenAssociations != null ? create.maxAutomaticTokenAssociations : undefined, stakedAccountId: create.stakedAccountId != null ? AccountId._fromProtobuf(create.stakedAccountId) : undefined, stakedNodeId: create.stakedNodeId != null ? create.stakedNodeId : undefined, declineStakingReward: create.declineReward == true, autoRenewAccountId: create.autoRenewAccountId != null ? AccountId._fromProtobuf(create.autoRenewAccountId) : undefined, }), transactions, signedTransactions, transactionIds, nodeIds, bodies, ); } /** * @returns {?FileId} */ get bytecodeFileId() { return this._bytecodeFileId; } /** * @param {FileId | string} bytecodeFileId * @returns {this} */ setBytecodeFileId(bytecodeFileId) { this._requireNotFrozen(); this._bytecodeFileId = typeof bytecodeFileId === "string" ? FileId.fromString(bytecodeFileId) : bytecodeFileId.clone(); this._bytecode = null; return this; } /** * @returns {?Uint8Array} */ get bytecode() { return this._bytecode; } /** * @param {Uint8Array} bytecode * @returns {this} */ setBytecode(bytecode) { this._requireNotFrozen(); this._bytecode = bytecode; this._bytecodeFileId = null; return this; } /** * @returns {?Key} */ get adminKey() { return this._adminKey; } /** * @param {Key} adminKey * @returns {this} */ setAdminKey(adminKey) { this._requireNotFrozen(); this._adminKey = adminKey; return this; } /** * @returns {?Long} */ get gas() { return this._gas; } /** * @param {number | Long} gas * @returns {this} */ setGas(gas) { this._requireNotFrozen(); this._gas = gas instanceof Long ? gas : Long.fromValue(gas); if (this._gas.lessThan(0)) { throw new Error("Gas cannot be negative number"); } return this; } /** * @returns {?Hbar} */ get initialBalance() { return this._initialBalance; } /** * Set the initial amount to transfer into this contract. * * @param {number | string | Long | BigNumber | Hbar} initialBalance * @returns {this} */ setInitialBalance(initialBalance) { this._requireNotFrozen(); this._initialBalance = initialBalance instanceof Hbar ? initialBalance : new Hbar(initialBalance); return this; } /** * @deprecated * @returns {?AccountId} */ get proxyAccountId() { return this._proxyAccountId; } /** * @deprecated * @param {AccountId | string} proxyAccountId * @returns {this} */ setProxyAccountId(proxyAccountId) { this._requireNotFrozen(); this._proxyAccountId = proxyAccountId instanceof AccountId ? proxyAccountId : AccountId.fromString(proxyAccountId); return this; } /** * @returns {Duration} */ get autoRenewPeriod() { return this._autoRenewPeriod; } /** * An account to charge for auto-renewal of this contract. If not set, or set to an * account with zero hbar balance, the contract's own hbar balance will be used to * cover auto-renewal fees. * * @param {Duration | Long | number} autoRenewPeriod * @returns {this} */ setAutoRenewPeriod(autoRenewPeriod) { this._requireNotFrozen(); this._autoRenewPeriod = autoRenewPeriod instanceof Duration ? autoRenewPeriod : new Duration(autoRenewPeriod); return this; } /** * @returns {?Uint8Array} */ get constructorParameters() { return this._constructorParameters; } /** * @param {Uint8Array | ContractFunctionParameters} constructorParameters * @returns {this} */ setConstructorParameters(constructorParameters) { this._requireNotFrozen(); this._constructorParameters = constructorParameters instanceof ContractFunctionParameters ? constructorParameters._build() : constructorParameters; return this; } /** * @returns {?string} */ get contractMemo() { return this._contractMemo; } /** * @param {string} contractMemo * @returns {this} */ setContractMemo(contractMemo) { this._requireNotFrozen(); this._contractMemo = contractMemo; return this; } /** * @returns {?number} */ get maxAutomaticTokenAssociations() { return this._maxAutomaticTokenAssociations; } /** * @param {number} maxAutomaticTokenAssociations * @returns {this} */ setMaxAutomaticTokenAssociations(maxAutomaticTokenAssociations) { this._maxAutomaticTokenAssociations = maxAutomaticTokenAssociations; return this; } /** * @returns {?AccountId} */ get stakedAccountId() { return this._stakedAccountId; } /** * @param {AccountId | string} stakedAccountId * @returns {this} */ setStakedAccountId(stakedAccountId) { this._requireNotFrozen(); this._stakedAccountId = typeof stakedAccountId === "string" ? AccountId.fromString(stakedAccountId) : stakedAccountId; this._stakedNodeId = null; return this; } /** * @returns {?Long} */ get stakedNodeId() { return this._stakedNodeId; } /** * @param {Long | number} stakedNodeId * @returns {this} */ setStakedNodeId(stakedNodeId) { this._requireNotFrozen(); this._stakedNodeId = Long.fromValue(stakedNodeId); this._stakedAccountId = null; return this; } /** * @returns {boolean} */ get declineStakingRewards() { return this._declineStakingReward; } /** * @param {boolean} declineStakingReward * @returns {this} */ setDeclineStakingReward(declineStakingReward) { this._requireNotFrozen(); this._declineStakingReward = declineStakingReward; return this; } /** * @returns {?AccountId} */ get autoRenewAccountId() { return this._autoRenewAccountId; } /** * @param {string | AccountId} autoRenewAccountId * @returns {this} */ setAutoRenewAccountId(autoRenewAccountId) { this._requireNotFrozen(); this._autoRenewAccountId = typeof autoRenewAccountId === "string" ? AccountId.fromString(autoRenewAccountId) : autoRenewAccountId; return this; } /** * @param {Client} client */ _validateChecksums(client) { if (this._bytecodeFileId != null) { this._bytecodeFileId.validateChecksum(client); } if (this._proxyAccountId != null) { this._proxyAccountId.validateChecksum(client); } } /** * @override * @internal * @param {Channel} channel * @param {HieroProto.proto.ITransaction} request * @returns {Promise<HieroProto.proto.ITransactionResponse>} */ _execute(channel, request) { return channel.smartContract.createContract(request); } /** * @override * @protected * @returns {NonNullable<HieroProto.proto.TransactionBody["data"]>} */ _getTransactionDataCase() { return "contractCreateInstance"; } /** * @override * @protected * @returns {HieroProto.proto.IContractCreateTransactionBody} */ _makeTransactionData() { return { fileID: this._bytecodeFileId != null ? this._bytecodeFileId._toProtobuf() : null, initcode: this._bytecode, adminKey: this._adminKey != null ? this._adminKey._toProtobufKey() : null, gas: this._gas, initialBalance: this._initialBalance != null ? this._initialBalance.toTinybars() : null, proxyAccountID: this._proxyAccountId != null ? this._proxyAccountId._toProtobuf() : null, autoRenewPeriod: this._autoRenewPeriod._toProtobuf(), constructorParameters: this._constructorParameters, memo: this._contractMemo, maxAutomaticTokenAssociations: this._maxAutomaticTokenAssociations, stakedAccountId: this.stakedAccountId != null ? this.stakedAccountId._toProtobuf() : null, stakedNodeId: this.stakedNodeId, declineReward: this.declineStakingRewards, autoRenewAccountId: this._autoRenewAccountId != null ? this._autoRenewAccountId._toProtobuf() : null, }; } /** * @returns {string} */ _getLogId() { const timestamp = /** @type {import("../Timestamp.js").default} */ ( this._transactionIds.current.validStart ); return `ContractCreateTransaction:${timestamp.toString()}`; } } TRANSACTION_REGISTRY.set( "contractCreateInstance", // eslint-disable-next-line @typescript-eslint/unbound-method ContractCreateTransaction._fromProtobuf, );