From 537797da631f0623ec91f9d10e6d6604a060299f Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Mon, 18 Mar 2024 10:45:03 +0200 Subject: [PATCH 01/30] feature: mutable metadata fields for dynamic NFTs Signed-off-by: svetoslav-nikol0v --- examples/update-nfts-metadata.js | 88 ++++++ package.json | 6 +- packages/proto/src/proto | 2 +- pnpm-lock.yaml | 12 +- src/exports.js | 1 + src/token/TokenCreateTransaction.js | 37 +++ src/token/TokenInfo.js | 16 ++ src/token/TokenNftsUpdateTransaction.js | 256 ++++++++++++++++++ src/token/TokenUpdateTransaction.js | 37 +++ ...kenNftsUpdateTransactionIntegrationTest.js | 111 ++++++++ 10 files changed, 552 insertions(+), 14 deletions(-) create mode 100644 examples/update-nfts-metadata.js create mode 100644 src/token/TokenNftsUpdateTransaction.js create mode 100644 test/integration/TokenNftsUpdateTransactionIntegrationTest.js diff --git a/examples/update-nfts-metadata.js b/examples/update-nfts-metadata.js new file mode 100644 index 000000000..298de5424 --- /dev/null +++ b/examples/update-nfts-metadata.js @@ -0,0 +1,88 @@ +import { TokenCreateTransaction, TokenInfoQuery, TokenType, PrivateKey, Client, AccountId, TokenMintTransaction, TokenNftsUpdateTransaction } from "@hashgraph/sdk"; +import dotenv from "dotenv"; + +dotenv.config(); + +/** + * @notice E2E-HIP-657 + * @url https://hips.hedera.com/hip/hip-657 + */ +async function main() { + if ( + !process.env.OPERATOR_KEY || + !process.env.OPERATOR_ID || + !process.env.HEDERA_NETWORK + ) { + throw new Error("Please set required keys in .env file."); + } + + const operatorId = AccountId.fromString(process.env.OPERATOR_ID); + const operatorKey = PrivateKey.fromStringDer(process.env.OPERATOR_KEY); + const network = process.env.HEDERA_NETWORK + const client = Client.forName(network).setOperator(operatorId, operatorKey); + const metadataKey = PrivateKey.generateECDSA() + console.log(`Generated metadata key: ${metadataKey.toString()}`); + + // Set initial metadate + const metadata = new Uint8Array(1) + // Set updated metadate + const updatedMetadata = new Uint8Array(2) + + try { + // Create token + let createTokenTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setTreasuryAccountId(operatorId) + .setSupplyKey(operatorKey) + .setMetadataKey(metadataKey) + .freezeWith(client) + + const tokenCreateResponse = await (await createTokenTx.sign(operatorKey)).execute(client) + // Get receipt for create token transaction + const tokenCreateReceipt = await tokenCreateResponse.getReceipt(client); + console.log(`Status of token create transction: ${tokenCreateReceipt.status.toString()}`); + + const tokenId = tokenCreateReceipt.tokenId; + console.log(`Token id: ${tokenId.toString()}`); + + // Get token info + const tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(client); + console.log(`Token metadata key: ${tokenInfo.metadataKey.toString()}`); + + // Mint token + const tokenMintTx = new TokenMintTransaction() + .setMetadata([metadata]) + .setTokenId(tokenId) + console.log(`Set metadata: ${tokenMintTx.metadata}`); + + const tokenMintResponse = await tokenMintTx.execute(client); + // Get receipt for mint token transaction + const tokenMintReceipt = await tokenMintResponse.getReceipt(client); + console.log(`Status of token mint transction: ${tokenMintReceipt.status.toString()}`); + + // Update nfts metadata + const tokenUpdateNftsTx = new TokenNftsUpdateTransaction() + .setTokenId(tokenId) + .setSerialNumbers(tokenMintReceipt.serials) + .setMetadata(updatedMetadata) + .freezeWith(client) + console.log(`Updatetd metadata: ${tokenUpdateNftsTx.metadata}`); + + const tokenUpdateNftsResponse = await(await tokenUpdateNftsTx.sign(metadataKey)).execute(client) + // Get receipt for update nfts metadata transaction + const tokenUpdateNftsReceipt = await tokenUpdateNftsResponse.getReceipt(client); + console.log(`Status of token update bfts metadata transction: ${tokenUpdateNftsReceipt.status.toString()}`); + } catch(error){ + console.log(error); + } + + client.close() +} + +void main(); diff --git a/package.json b/package.json index e26d854b5..2e2148efe 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "@ethersproject/rlp": "^5.7.0", "@grpc/grpc-js": "1.8.2", "@hashgraph/cryptography": "1.4.8-beta.5", - "@hashgraph/proto": "2.14.0-beta.5", + "@hashgraph/proto": "link:packages/proto", "axios": "^1.6.4", "bignumber.js": "^9.1.1", "bn.js": "^5.1.1", @@ -68,8 +68,8 @@ "pino": "^8.14.1", "pino-pretty": "^10.0.0", "protobufjs": "^7.2.5", - "utf8": "^3.0.0", - "rfc4648": "^1.5.3" + "rfc4648": "^1.5.3", + "utf8": "^3.0.0" }, "devDependencies": { "@babel/cli": "^7.23.4", diff --git a/packages/proto/src/proto b/packages/proto/src/proto index 6d41db355..98efa7c00 160000 --- a/packages/proto/src/proto +++ b/packages/proto/src/proto @@ -1 +1 @@ -Subproject commit 6d41db35567c63073fd32be70cdae601a9e19aaf +Subproject commit 98efa7c00368b052cfffb91e5d72b47e3263965e diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ae75d2b82..27058ceb8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,8 +24,8 @@ dependencies: specifier: 1.4.8-beta.5 version: 1.4.8-beta.5(expo@49.0.20) '@hashgraph/proto': - specifier: 2.14.0-beta.5 - version: 2.14.0-beta.5 + specifier: link:packages/proto + version: link:packages/proto axios: specifier: ^1.6.4 version: 1.6.5 @@ -2675,14 +2675,6 @@ packages: utf8: 3.0.0 dev: false - /@hashgraph/proto@2.14.0-beta.5: - resolution: {integrity: sha512-UrIbLdctpD//Ua99Z4PnknbR8220nc1Pzv0nkDJ1emZE9EAi7YOOry2Dw660azQHWfVw/HhqECPdiKrTIZ2b+Q==} - engines: {node: '>=10.0.0'} - dependencies: - long: 4.0.0 - protobufjs: 7.2.5 - dev: false - /@humanwhocodes/config-array@0.11.13: resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} diff --git a/src/exports.js b/src/exports.js index 290940718..7d98dfbc2 100644 --- a/src/exports.js +++ b/src/exports.js @@ -180,6 +180,7 @@ export { default as StatusError } from "./StatusError.js"; export { default as PrecheckStatusError } from "./PrecheckStatusError.js"; export { default as ReceiptStatusError } from "./ReceiptStatusError.js"; export { default as LedgerId } from "./LedgerId.js"; +export { default as TokenNftsUpdateTransaction } from "./token/TokenNftsUpdateTransaction.js"; /** * @typedef {import("./client/Client.js").NetworkName} ClientNetworkName diff --git a/src/token/TokenCreateTransaction.js b/src/token/TokenCreateTransaction.js index 0ea8b030a..d1a597ee6 100644 --- a/src/token/TokenCreateTransaction.js +++ b/src/token/TokenCreateTransaction.js @@ -80,6 +80,7 @@ export default class TokenCreateTransaction extends Transaction { * @param {TokenType} [props.tokenType] * @param {TokenSupplyType} [props.supplyType] * @param {Long | number} [props.maxSupply] + * @param {Key} [props.metadataKey] */ constructor(props = {}) { super(); @@ -217,6 +218,12 @@ export default class TokenCreateTransaction extends Transaction { this._defaultMaxTransactionFee = new Hbar(30); + /** + * @private + * @type {?Key} + */ + this._metadataKey = null; + if (props.tokenName != null) { this.setTokenName(props.tokenName); } @@ -300,6 +307,10 @@ export default class TokenCreateTransaction extends Transaction { if (props.maxSupply != null) { this.setMaxSupply(props.maxSupply); } + + if (props.metadataKey != null) { + this.setMetadataKey(props.metadataKey); + } } /** @@ -404,6 +415,10 @@ export default class TokenCreateTransaction extends Transaction { : undefined, maxSupply: create.maxSupply != null ? create.maxSupply : undefined, + metadataKey: + create.metadataKey != null + ? Key._fromProtobufKey(create.metadataKey) + : undefined, }), transactions, signedTransactions, @@ -795,6 +810,24 @@ export default class TokenCreateTransaction extends Transaction { return this; } + /** + * @returns {?Key} + */ + get metadataKey() { + return this._metadataKey; + } + + /** + * @param {Key} key + * @returns {this} + */ + setMetadataKey(key) { + this._requireNotFrozen(); + this._metadataKey = key; + + return this; + } + /** * @param {Client} client */ @@ -881,6 +914,10 @@ export default class TokenCreateTransaction extends Transaction { supplyType: this._supplyType != null ? this._supplyType._code : null, maxSupply: this.maxSupply, + metadataKey: + this._metadataKey != null + ? this._metadataKey._toProtobufKey() + : null, }; } diff --git a/src/token/TokenInfo.js b/src/token/TokenInfo.js index 692ec57f7..f95a41942 100644 --- a/src/token/TokenInfo.js +++ b/src/token/TokenInfo.js @@ -69,6 +69,7 @@ export default class TokenInfo { * @param {TokenSupplyType | null} props.supplyType; * @param {Long | null} props.maxSupply; * @param {LedgerId|null} props.ledgerId + * @param {Key | null} props.metadataKey */ constructor(props) { /** @@ -238,6 +239,13 @@ export default class TokenInfo { this.maxSupply = props.maxSupply; this.ledgerId = props.ledgerId; + + /** + * The key which can change the metadata of a token (token definition and individual NFTs). + * + * @readonly + */ + this.metadataKey = props.metadataKey; } /** @@ -361,6 +369,10 @@ export default class TokenInfo { info.ledgerId != null ? LedgerId.fromBytes(info.ledgerId) : null, + metadataKey: + info.metadataKey != null + ? Key._fromProtobufKey(info.metadataKey) + : null, }); } @@ -426,6 +438,10 @@ export default class TokenInfo { supplyType: this.supplyType != null ? this.supplyType._code : null, maxSupply: this.maxSupply, ledgerId: this.ledgerId != null ? this.ledgerId.toBytes() : null, + metadataKey: + this.metadataKey != null + ? this.metadataKey._toProtobufKey() + : null, }; } diff --git a/src/token/TokenNftsUpdateTransaction.js b/src/token/TokenNftsUpdateTransaction.js new file mode 100644 index 000000000..28a334ed0 --- /dev/null +++ b/src/token/TokenNftsUpdateTransaction.js @@ -0,0 +1,256 @@ +/*- + * ‌ + * Hedera JavaScript SDK + * ​ + * Copyright (C) 2020 - 2023 Hedera Hashgraph, LLC + * ​ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ‍ + */ + +import TokenId from "./TokenId.js"; +import Transaction, { + TRANSACTION_REGISTRY, +} from "../transaction/Transaction.js"; + +/** + * @namespace proto + * @typedef {import("@hashgraph/proto").proto.ITransaction} HashgraphProto.proto.ITransaction + * @typedef {import("@hashgraph/proto").proto.ISignedTransaction} HashgraphProto.proto.ISignedTransaction + * @typedef {import("@hashgraph/proto").proto.TransactionBody} HashgraphProto.proto.TransactionBody + * @typedef {import("@hashgraph/proto").proto.ITransactionBody} HashgraphProto.proto.ITransactionBody + * @typedef {import("@hashgraph/proto").proto.ITransactionResponse} HashgraphProto.proto.ITransactionResponse + * @typedef {import("@hashgraph/proto").proto.ITokenUpdateNftsTransactionBody} HashgraphProto.proto.ITokenUpdateNftsTransactionBody + * @typedef {import("@hashgraph/proto").proto.ITokenID} HashgraphProto.proto.ITokenID + */ + +/** + * @typedef {import("../channel/Channel.js").default} Channel + * @typedef {import("../client/Client.js").default<*, *>} Client + * @typedef {import("../transaction/TransactionId.js").default} TransactionId + * @typedef {import("../account/AccountId.js").default} AccountId + */ + +/** + * Pause a new Hedera™ crypto-currency token. + */ +export default class TokenNftsUpdateTransaction extends Transaction { + /** + * @param {object} [props] + * @param {TokenId | string} [props.tokenId] + * @param {Long[]} [props.serialNumbers] + * @param {Uint8Array} [props.metadata] + */ + constructor(props = {}) { + super(); + + /** + * @private + * @type {?TokenId} + */ + this._tokenId = null; + + /** + * @private + * @type {?Long[]} + */ + this._serialNumbers = []; + + /** + * @private + * @type {?Uint8Array} + */ + this._metadata = null; + + if (props.tokenId != null) { + this.setTokenId(props.tokenId); + } + + if (props.serialNumbers != null) { + this.setSerialNumbers(props.serialNumbers); + } + + if (props.metadata != null) { + this.setMetadata(props.metadata); + } + } + + /** + * @internal + * @param {HashgraphProto.proto.ITransaction[]} transactions + * @param {HashgraphProto.proto.ISignedTransaction[]} signedTransactions + * @param {TransactionId[]} transactionIds + * @param {AccountId[]} nodeIds + * @param {HashgraphProto.proto.ITransactionBody[]} bodies + * @returns {TokenNftsUpdateTransaction} + */ + static _fromProtobuf( + transactions, + signedTransactions, + transactionIds, + nodeIds, + bodies, + ) { + const body = bodies[0]; + const tokenUpdate = + /** @type {HashgraphProto.proto.ITokenUpdateNftsTransactionBody} */ ( + body.tokenUpdate + ); + + return Transaction._fromProtobufTransactions( + new TokenNftsUpdateTransaction({ + tokenId: + tokenUpdate.token != null + ? TokenId._fromProtobuf(tokenUpdate.token) + : undefined, + serialNumbers: + tokenUpdate.serialNumbers != null + ? tokenUpdate.serialNumbers + : [], + metadata: + tokenUpdate.metadata != null + ? tokenUpdate.metadata.value != null + ? tokenUpdate.metadata.value + : undefined + : undefined, + }), + transactions, + signedTransactions, + transactionIds, + nodeIds, + bodies, + ); + } + + /** + * @description Extract the token id. Returns the token id. + * @returns {?TokenId} + */ + get tokenId() { + return this._tokenId; + } + + /** + * @description Assign the token id. + * @param {TokenId | string} tokenId + * @returns {this} + */ + setTokenId(tokenId) { + this._requireNotFrozen(); + this._tokenId = + typeof tokenId === "string" + ? TokenId.fromString(tokenId) + : tokenId.clone(); + + return this; + } + + /** + * @description Extract the list of serial numbers. Returns the list of serial numbers. + * @returns {?Long[]} + */ + get serialNumbers() { + return this._serialNumbers; + } + + /** + * @description Assign the list of serial numbers. + * @param {Long[]} serialNumbers + * @returns {this} + */ + setSerialNumbers(serialNumbers) { + this._requireNotFrozen(); + this._serialNumbers = serialNumbers; + + return this; + } + + /** + * @returns {?Uint8Array} + */ + get metadata() { + return this._metadata; + } + + /** + * @param {Uint8Array} metadata + * @returns {this} + */ + setMetadata(metadata) { + this._requireNotFrozen(); + this._metadata = metadata; + + return this; + } + + /** + * @param {Client} client + */ + _validateChecksums(client) { + if (this._tokenId != null) { + this._tokenId.validateChecksum(client); + } + } + + /** + * @override + * @internal + * @param {Channel} channel + * @param {HashgraphProto.proto.ITransaction} request + * @returns {Promise} + */ + _execute(channel, request) { + return channel.token.pauseToken(request); + } + + /** + * @override + * @protected + * @returns {NonNullable} + */ + _getTransactionDataCase() { + return "tokenUpdateNfts"; + } + + /** + * @override + * @protected + * @returns {HashgraphProto.proto.ITokenUpdateNftsTransactionBody} + */ + _makeTransactionData() { + return { + token: this._tokenId != null ? this._tokenId._toProtobuf() : null, + serialNumbers: + this._serialNumbers != null ? this._serialNumbers : [], + metadata: { + value: this._metadata != null ? this._metadata : null, + }, + }; + } + + /** + * @returns {string} + */ + _getLogId() { + const timestamp = /** @type {import("../Timestamp.js").default} */ ( + this._transactionIds.current.validStart + ); + return `TokenNftsUpdateTransaction:${timestamp.toString()}`; + } +} + +TRANSACTION_REGISTRY.set( + "tokenUpdateNfts", + // eslint-disable-next-line @typescript-eslint/unbound-method + TokenNftsUpdateTransaction._fromProtobuf, +); diff --git a/src/token/TokenUpdateTransaction.js b/src/token/TokenUpdateTransaction.js index 15cd07281..5e23ebf9e 100644 --- a/src/token/TokenUpdateTransaction.js +++ b/src/token/TokenUpdateTransaction.js @@ -66,6 +66,7 @@ export default class TokenUpdateTransaction extends Transaction { * @param {string} [props.tokenMemo] * @param {Key} [props.feeScheduleKey] * @param {Key} [props.pauseKey] + * @param {Key} [props.metadataKey] */ constructor(props = {}) { super(); @@ -160,6 +161,12 @@ export default class TokenUpdateTransaction extends Transaction { */ this._pauseKey = null; + /** + * @private + * @type {?Key} + */ + this._metadataKey = null; + if (props.tokenId != null) { this.setTokenId(props.tokenId); } @@ -219,6 +226,10 @@ export default class TokenUpdateTransaction extends Transaction { if (props.pauseKey != null) { this.setPauseKey(props.pauseKey); } + + if (props.metadataKey != null) { + this.setMetadataKey(props.metadataKey); + } } /** @@ -301,6 +312,10 @@ export default class TokenUpdateTransaction extends Transaction { update.pauseKey != null ? Key._fromProtobufKey(update.pauseKey) : undefined, + metadataKey: + update.metadataKey != null + ? Key._fromProtobufKey(update.metadataKey) + : undefined, }), transactions, signedTransactions, @@ -602,6 +617,24 @@ export default class TokenUpdateTransaction extends Transaction { return this; } + /** + * @returns {?Key} + */ + get metadataKey() { + return this._metadataKey; + } + + /** + * @param {Key} metadataKey + * @returns {this} + */ + setMetadataKey(metadataKey) { + this._requireNotFrozen(); + this._metadataKey = metadataKey; + + return this; + } + /** * @returns {this} */ @@ -700,6 +733,10 @@ export default class TokenUpdateTransaction extends Transaction { this._feeScheduleKey != null ? this._feeScheduleKey._toProtobufKey() : null, + metadataKey: + this._metadataKey != null + ? this._metadataKey._toProtobufKey() + : null, }; } diff --git a/test/integration/TokenNftsUpdateTransactionIntegrationTest.js b/test/integration/TokenNftsUpdateTransactionIntegrationTest.js new file mode 100644 index 000000000..4d54c9f16 --- /dev/null +++ b/test/integration/TokenNftsUpdateTransactionIntegrationTest.js @@ -0,0 +1,111 @@ +import { + TokenCreateTransaction, + TokenInfoQuery, + TokenType, + PrivateKey, + TransactionReceipt, + TransactionResponse, + TokenMintTransaction, + TokenNftsUpdateTransaction, + TokenId, + TokenInfo, +} from "../../src/exports.js"; +import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js"; + +describe.only("TokenNftsUpdateTransaction", function () { + let client, operatorId, operatorKey; + + before(async function () { + const env = await IntegrationTestEnv.new(); + client = env.client; + operatorId = env.operatorId; + operatorKey = env.operatorKey; + }); + + it("should update the inital metadata of nfts", async function () { + const metadataKey = PrivateKey.generateECDSA(); + const metadata = new Uint8Array(1); + const newMetadata = new Uint8Array(2); + + try { + let createTokenTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setTreasuryAccountId(operatorId) + .setSupplyKey(operatorKey) + .setMetadataKey(metadataKey) + .freezeWith(client); + expect(createTokenTx.tokenName).to.be.equal("Test"); + expect(createTokenTx.tokenSymbol).to.be.equal("T"); + expect(createTokenTx.tokenType).to.be.equal( + TokenType.NonFungibleUnique, + ); + expect(createTokenTx.treasuryAccountId.toString()).to.be.equal( + operatorId.toString(), + ); + expect(createTokenTx.adminKey.toString()).to.be.equal( + operatorKey.toString(), + ); + expect(createTokenTx.supplyKey.toString()).to.be.equal( + operatorKey.toString(), + ); + expect(createTokenTx.metadataKey.toString()).to.be.equal( + metadataKey.toString(), + ); + + const createTokenResponse = await ( + await createTokenTx.sign(operatorKey) + ).execute(client); + expect(createTokenResponse).to.be.instanceof(TransactionResponse); + + const createTokenReceipt = + await createTokenResponse.getReceipt(client); + expect(createTokenReceipt).to.be.instanceof(TransactionReceipt); + + const tokenId = createTokenReceipt.tokenId; + expect(tokenId).to.be.instanceof(TokenId); + + const tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(client); + expect(tokenInfo).to.be.instanceof(TokenInfo); + + const tokenMintTx = new TokenMintTransaction() + .setMetadata([metadata]) + .setTokenId(tokenId); + + const tokenMintResponse = await tokenMintTx.execute(client); + expect(tokenMintResponse).to.be.instanceof(TransactionResponse); + + const tokenMintReceipt = await tokenMintResponse.getReceipt(client); + expect(tokenMintReceipt).to.be.instanceof(TransactionReceipt); + + const tokenUpdateNftsTx = new TokenNftsUpdateTransaction() + .setTokenId(tokenId) + .setSerialNumbers(tokenMintReceipt.serials) + .setMetadata(newMetadata) + .freezeWith(client); + + const tokenUpdateNftsResponse = await ( + await tokenUpdateNftsTx.sign(metadataKey) + ).execute(client); + expect(tokenUpdateNftsResponse).to.be.instanceof( + TransactionResponse, + ); + + const tokenUpdateNftsReceipt = + await tokenUpdateNftsResponse.getReceipt(client); + expect(tokenUpdateNftsReceipt).to.be.instanceof(TransactionReceipt); + } catch (error) { + console.log(error); + } + }); + + it("should return INVALID_METADATA_KEY error", async function () {}); + it("should return TOKEN_HAS_NO_METADATA_KEY error", async function () {}); + it("should return MISSING_TOKEN_METADATA error", async function () {}); + it("should return MISSING_SERIAL_NUMBERS error", async function () {}); +}); From 37b292dd987e7c23c7cfe59b18d59f842825be95 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Mon, 18 Mar 2024 11:03:30 +0200 Subject: [PATCH 02/30] update: TokenCreateTransaction class and related intergration test Signed-off-by: svetoslav-nikol0v --- src/token/TokenCreateTransaction.js | 38 +++++++++++++++++++ .../integration/TokenCreateIntegrationTest.js | 6 +++ 2 files changed, 44 insertions(+) diff --git a/src/token/TokenCreateTransaction.js b/src/token/TokenCreateTransaction.js index d1a597ee6..d85c75b41 100644 --- a/src/token/TokenCreateTransaction.js +++ b/src/token/TokenCreateTransaction.js @@ -81,6 +81,7 @@ export default class TokenCreateTransaction extends Transaction { * @param {TokenSupplyType} [props.supplyType] * @param {Long | number} [props.maxSupply] * @param {Key} [props.metadataKey] + * @param {Uint8Array} [props.metadata] */ constructor(props = {}) { super(); @@ -224,6 +225,13 @@ export default class TokenCreateTransaction extends Transaction { */ this._metadataKey = null; + /** + * @private + * @description Metadata of the created token definition. + * @type {?Uint8Array} + */ + this._metadata = null; + if (props.tokenName != null) { this.setTokenName(props.tokenName); } @@ -311,6 +319,10 @@ export default class TokenCreateTransaction extends Transaction { if (props.metadataKey != null) { this.setMetadataKey(props.metadataKey); } + + if (props.metadata != null) { + this.setMetadata(props.metadata); + } } /** @@ -419,6 +431,10 @@ export default class TokenCreateTransaction extends Transaction { create.metadataKey != null ? Key._fromProtobufKey(create.metadataKey) : undefined, + metadata: + create.metadata != null + ? create.metadata + : undefined, }), transactions, signedTransactions, @@ -828,6 +844,24 @@ export default class TokenCreateTransaction extends Transaction { return this; } + /** + * @returns {?Uint8Array} + */ + get metadata() { + return this._metadata; + } + + /** + * @param {Uint8Array} metadata + * @returns {this} + */ + setMetadata(metadata) { + this._requireNotFrozen(); + this._metadata = metadata; + + return this; + } + /** * @param {Client} client */ @@ -918,6 +952,10 @@ export default class TokenCreateTransaction extends Transaction { this._metadataKey != null ? this._metadataKey._toProtobufKey() : null, + metadata: + this._metadata != null + ? this._metadata + : undefined, }; } diff --git a/test/integration/TokenCreateIntegrationTest.js b/test/integration/TokenCreateIntegrationTest.js index fd50af46b..abf248a1c 100644 --- a/test/integration/TokenCreateIntegrationTest.js +++ b/test/integration/TokenCreateIntegrationTest.js @@ -23,6 +23,8 @@ describe("TokenCreate", function () { const key2 = PrivateKey.generateED25519(); const key3 = PrivateKey.generateED25519(); const key4 = PrivateKey.generateED25519(); + const metadataKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array(1); const response = await new TokenCreateTransaction() .setTokenName("ffff") @@ -36,6 +38,8 @@ describe("TokenCreate", function () { .setWipeKey(key3) .setSupplyKey(key4) .setFreezeDefault(false) + .setMetadataKey(metadataKey) + .setMetadata(metadata) .execute(env.client); const tokenId = (await response.getReceipt(env.client)).tokenId; @@ -63,6 +67,8 @@ describe("TokenCreate", function () { expect(info.autoRenewAccountId).to.be.null; expect(info.autoRenewPeriod).to.be.null; expect(info.expirationTime).to.be.not.null; + expect(info.metadataKey).to.eql(metadataKey.toString()); + expect(info.metadata).to.eql(metadata); }); it("should be executable with minimal properties set", async function () { From f04f6444baf281886a7c396d5719ad51cbf399a5 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Mon, 18 Mar 2024 11:33:51 +0200 Subject: [PATCH 03/30] update: TokenUpdateTransaction class and integration test Signed-off-by: svetoslav-nikol0v --- src/token/TokenUpdateTransaction.js | 41 +++++++++++++++++++ ...kenNftsUpdateTransactionIntegrationTest.js | 2 +- .../integration/TokenUpdateIntegrationTest.js | 17 +++++--- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/token/TokenUpdateTransaction.js b/src/token/TokenUpdateTransaction.js index 5e23ebf9e..f11b74bd5 100644 --- a/src/token/TokenUpdateTransaction.js +++ b/src/token/TokenUpdateTransaction.js @@ -67,6 +67,7 @@ export default class TokenUpdateTransaction extends Transaction { * @param {Key} [props.feeScheduleKey] * @param {Key} [props.pauseKey] * @param {Key} [props.metadataKey] + * @param {Uint8Array} [props.metadata] */ constructor(props = {}) { super(); @@ -167,6 +168,12 @@ export default class TokenUpdateTransaction extends Transaction { */ this._metadataKey = null; + /** + * @private + * @type {?Uint8Array} + */ + this._metadata = null; + if (props.tokenId != null) { this.setTokenId(props.tokenId); } @@ -230,6 +237,10 @@ export default class TokenUpdateTransaction extends Transaction { if (props.metadataKey != null) { this.setMetadataKey(props.metadataKey); } + + if (props.metadata != null) { + this.setMetadata(props.metadata); + } } /** @@ -316,6 +327,12 @@ export default class TokenUpdateTransaction extends Transaction { update.metadataKey != null ? Key._fromProtobufKey(update.metadataKey) : undefined, + metadata: + update.metadata != null + ? update.metadata.value != null + ? update.metadata.value + : undefined + : undefined }), transactions, signedTransactions, @@ -635,6 +652,24 @@ export default class TokenUpdateTransaction extends Transaction { return this; } + /** + * @returns {?Uint8Array} + */ + get metadata() { + return this._metadata; + } + + /** + * @param {Uint8Array} metadata + * @returns {this} + */ + setMetadata(metadata) { + this._requireNotFrozen(); + this._metadata = metadata; + + return this; + } + /** * @returns {this} */ @@ -737,6 +772,12 @@ export default class TokenUpdateTransaction extends Transaction { this._metadataKey != null ? this._metadataKey._toProtobufKey() : null, + metadata: + this._metadata != null + ? { + value: this._metadata + } + : null }; } diff --git a/test/integration/TokenNftsUpdateTransactionIntegrationTest.js b/test/integration/TokenNftsUpdateTransactionIntegrationTest.js index 4d54c9f16..55541e1bd 100644 --- a/test/integration/TokenNftsUpdateTransactionIntegrationTest.js +++ b/test/integration/TokenNftsUpdateTransactionIntegrationTest.js @@ -12,7 +12,7 @@ import { } from "../../src/exports.js"; import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js"; -describe.only("TokenNftsUpdateTransaction", function () { +describe("TokenNftsUpdateTransaction", function () { let client, operatorId, operatorKey; before(async function () { diff --git a/test/integration/TokenUpdateIntegrationTest.js b/test/integration/TokenUpdateIntegrationTest.js index e40fb3fe1..859501f88 100644 --- a/test/integration/TokenUpdateIntegrationTest.js +++ b/test/integration/TokenUpdateIntegrationTest.js @@ -31,6 +31,10 @@ describe("TokenUpdate", function () { const key3 = PrivateKey.generateED25519(); const key4 = PrivateKey.generateED25519(); const key5 = PrivateKey.generateED25519(); + const metadataKey = PrivateKey.generateED25519(); + const newMetadataKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array(1); + const newMetadata = new Uint8Array(2) const response = await new TokenCreateTransaction() .setTokenName("ffff") @@ -45,6 +49,8 @@ describe("TokenUpdate", function () { .setSupplyKey(key4) .setFreezeDefault(false) .setPauseKey(key5) + .setMetadataKey(metadataKey) + .setMetadata(metadata) .execute(env.client); const token = (await response.getReceipt(env.client)).tokenId; @@ -52,11 +58,6 @@ describe("TokenUpdate", function () { let info = await new TokenInfoQuery() .setTokenId(token) .execute(env.client); - - expect(info.tokenId.toString()).to.eql(token.toString()); - expect(info.name).to.eql("ffff"); - expect(info.symbol).to.eql("F"); - expect(info.decimals).to.eql(3); expect(info.totalSupply.toInt()).to.eql(1000000); expect(info.treasuryAccountId.toString()).to.be.equal( operatorId.toString(), @@ -73,12 +74,16 @@ describe("TokenUpdate", function () { expect(info.autoRenewAccountId).to.be.null; expect(info.autoRenewPeriod).to.be.null; expect(info.expirationTime).to.be.not.null; + expect(info.metadataKey.toString()).to.eql(metadataKey.toString()); + expect(info.metadata).to.eql(metadata); await ( await new TokenUpdateTransaction() .setTokenId(token) .setTokenName("aaaa") .setTokenSymbol("A") + .setMetadataKey(newMetadataKey) + .setMetadata(newMetadata) .execute(env.client) ).getReceipt(env.client); @@ -103,6 +108,8 @@ describe("TokenUpdate", function () { expect(info.autoRenewAccountId).to.be.null; expect(info.autoRenewPeriod).to.be.null; expect(info.expirationTime).to.be.not.null; + expect(info.metadataKey.toString()).to.eql(newMetadataKey.toString()); + expect(info.metadata).to.eql(newMetadata); }); it("should be able to update treasury", async function () { From 49f00b8cdbd73edb8daeb1f31752f7253cef037f Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Mon, 18 Mar 2024 11:35:38 +0200 Subject: [PATCH 04/30] update: TokenInfo class and integration test Signed-off-by: svetoslav-nikol0v --- ...fee-create-mint-burn-associate-transfer.js | 1 - src/token/TokenInfo.js | 23 +++++++++++++++---- test/integration/TopicInfoIntegrationTest.js | 2 ++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/examples/hts-nftP1-fee-create-mint-burn-associate-transfer.js b/examples/hts-nftP1-fee-create-mint-burn-associate-transfer.js index dcfecf1ab..0fe23e73a 100644 --- a/examples/hts-nftP1-fee-create-mint-burn-associate-transfer.js +++ b/examples/hts-nftP1-fee-create-mint-burn-associate-transfer.js @@ -77,7 +77,6 @@ async function main() { .setCustomFees([nftCustomFee]) .setAdminKey(adminKey) .setSupplyKey(supplyKey) - // .setPauseKey(pauseKey) .setFreezeKey(freezeKey) .setWipeKey(wipeKey) .freezeWith(client) diff --git a/src/token/TokenInfo.js b/src/token/TokenInfo.js index f95a41942..a75ddc452 100644 --- a/src/token/TokenInfo.js +++ b/src/token/TokenInfo.js @@ -42,7 +42,7 @@ import LedgerId from "../LedgerId.js"; export default class TokenInfo { /** * @private - * @param {object} props + * @param {object} props; * @param {TokenId} props.tokenId; * @param {string} props.name; * @param {string} props.symbol; @@ -68,8 +68,9 @@ export default class TokenInfo { * @param {TokenType | null} props.tokenType; * @param {TokenSupplyType | null} props.supplyType; * @param {Long | null} props.maxSupply; - * @param {LedgerId|null} props.ledgerId - * @param {Key | null} props.metadataKey + * @param {LedgerId|null} props.ledgerId; + * @param {Key | null} props.metadataKey; + * @param {Uint8Array} props.metadata; */ constructor(props) { /** @@ -241,11 +242,17 @@ export default class TokenInfo { this.ledgerId = props.ledgerId; /** - * The key which can change the metadata of a token (token definition and individual NFTs). + * @description The key which can change the metadata of a token (token definition and individual NFTs). * * @readonly */ this.metadataKey = props.metadataKey; + + /** + * @description Metadata of the created token definition. + * @readonly + */ + this.metadata = props.metadata; } /** @@ -373,6 +380,10 @@ export default class TokenInfo { info.metadataKey != null ? Key._fromProtobufKey(info.metadataKey) : null, + metadata: + info.metadata != null + ? info.metadata + : new Uint8Array(), }); } @@ -442,6 +453,10 @@ export default class TokenInfo { this.metadataKey != null ? this.metadataKey._toProtobufKey() : null, + metadata: + this.metadata != null + ? this.metadata + : null }; } diff --git a/test/integration/TopicInfoIntegrationTest.js b/test/integration/TopicInfoIntegrationTest.js index 3990ec045..e02e9d4db 100644 --- a/test/integration/TopicInfoIntegrationTest.js +++ b/test/integration/TopicInfoIntegrationTest.js @@ -42,6 +42,8 @@ describe("TopicInfo", function () { ); expect(info.autoRenewPeriod.seconds.toInt()).to.be.eql(7776000); expect(info.expirationTime).to.be.not.null; + expect(info.metadataKey).to.be.not.null; + expect(info.metadata).to.be.not.null; await ( await new TopicDeleteTransaction() From b7671e94ea15c30c8be9ea6eed18da1519618193 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Mon, 18 Mar 2024 13:12:06 +0200 Subject: [PATCH 05/30] chore: formatting Signed-off-by: svetoslav-nikol0v --- src/token/TokenInfo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/token/TokenInfo.js b/src/token/TokenInfo.js index a75ddc452..273f6b266 100644 --- a/src/token/TokenInfo.js +++ b/src/token/TokenInfo.js @@ -42,7 +42,7 @@ import LedgerId from "../LedgerId.js"; export default class TokenInfo { /** * @private - * @param {object} props; + * @param {object} props * @param {TokenId} props.tokenId; * @param {string} props.name; * @param {string} props.symbol; From 9c0351f18a8911a5e9f19d60119ca52c08c9802b Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Tue, 19 Mar 2024 09:55:54 +0200 Subject: [PATCH 06/30] chore: formatting Signed-off-by: svetoslav-nikol0v --- examples/update-nfts-metadata.js | 8 ++++---- src/token/TokenCreateTransaction.js | 14 ++++---------- src/token/TokenInfo.js | 12 +++--------- src/token/TokenUpdateTransaction.js | 10 +++++----- test/integration/TokenUpdateIntegrationTest.js | 2 +- 5 files changed, 17 insertions(+), 29 deletions(-) diff --git a/examples/update-nfts-metadata.js b/examples/update-nfts-metadata.js index 298de5424..fc4fb8ed8 100644 --- a/examples/update-nfts-metadata.js +++ b/examples/update-nfts-metadata.js @@ -24,9 +24,9 @@ async function main() { console.log(`Generated metadata key: ${metadataKey.toString()}`); // Set initial metadate - const metadata = new Uint8Array(1) + const metadata = new Uint8Array([1]) // Set updated metadate - const updatedMetadata = new Uint8Array(2) + const updatedMetadata = new Uint8Array([1, 2]) try { // Create token @@ -53,7 +53,7 @@ async function main() { const tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(client); - console.log(`Token metadata key: ${tokenInfo.metadataKey.toString()}`); + console.log(`Token metadata key: ${tokenInfo.metadataKey?.toString()}`); // Mint token const tokenMintTx = new TokenMintTransaction() @@ -72,7 +72,7 @@ async function main() { .setSerialNumbers(tokenMintReceipt.serials) .setMetadata(updatedMetadata) .freezeWith(client) - console.log(`Updatetd metadata: ${tokenUpdateNftsTx.metadata}`); + console.log(`Updateted metadata: ${tokenUpdateNftsTx.metadata}`); const tokenUpdateNftsResponse = await(await tokenUpdateNftsTx.sign(metadataKey)).execute(client) // Get receipt for update nfts metadata transaction diff --git a/src/token/TokenCreateTransaction.js b/src/token/TokenCreateTransaction.js index d85c75b41..e00ee8650 100644 --- a/src/token/TokenCreateTransaction.js +++ b/src/token/TokenCreateTransaction.js @@ -431,10 +431,7 @@ export default class TokenCreateTransaction extends Transaction { create.metadataKey != null ? Key._fromProtobufKey(create.metadataKey) : undefined, - metadata: - create.metadata != null - ? create.metadata - : undefined, + metadata: create.metadata != null ? create.metadata : undefined, }), transactions, signedTransactions, @@ -844,10 +841,10 @@ export default class TokenCreateTransaction extends Transaction { return this; } - /** + /** * @returns {?Uint8Array} */ - get metadata() { + get metadata() { return this._metadata; } @@ -952,10 +949,7 @@ export default class TokenCreateTransaction extends Transaction { this._metadataKey != null ? this._metadataKey._toProtobufKey() : null, - metadata: - this._metadata != null - ? this._metadata - : undefined, + metadata: this._metadata != null ? this._metadata : undefined, }; } diff --git a/src/token/TokenInfo.js b/src/token/TokenInfo.js index 273f6b266..516858420 100644 --- a/src/token/TokenInfo.js +++ b/src/token/TokenInfo.js @@ -70,7 +70,7 @@ export default class TokenInfo { * @param {Long | null} props.maxSupply; * @param {LedgerId|null} props.ledgerId; * @param {Key | null} props.metadataKey; - * @param {Uint8Array} props.metadata; + * @param {Uint8Array | null} props.metadata; */ constructor(props) { /** @@ -380,10 +380,7 @@ export default class TokenInfo { info.metadataKey != null ? Key._fromProtobufKey(info.metadataKey) : null, - metadata: - info.metadata != null - ? info.metadata - : new Uint8Array(), + metadata: info.metadata != null ? info.metadata : new Uint8Array(), }); } @@ -453,10 +450,7 @@ export default class TokenInfo { this.metadataKey != null ? this.metadataKey._toProtobufKey() : null, - metadata: - this.metadata != null - ? this.metadata - : null + metadata: this.metadata != null ? this.metadata : null, }; } diff --git a/src/token/TokenUpdateTransaction.js b/src/token/TokenUpdateTransaction.js index f11b74bd5..8c73e30c0 100644 --- a/src/token/TokenUpdateTransaction.js +++ b/src/token/TokenUpdateTransaction.js @@ -332,7 +332,7 @@ export default class TokenUpdateTransaction extends Transaction { ? update.metadata.value != null ? update.metadata.value : undefined - : undefined + : undefined, }), transactions, signedTransactions, @@ -774,10 +774,10 @@ export default class TokenUpdateTransaction extends Transaction { : null, metadata: this._metadata != null - ? { - value: this._metadata - } - : null + ? { + value: this._metadata, + } + : null, }; } diff --git a/test/integration/TokenUpdateIntegrationTest.js b/test/integration/TokenUpdateIntegrationTest.js index 859501f88..29debd87e 100644 --- a/test/integration/TokenUpdateIntegrationTest.js +++ b/test/integration/TokenUpdateIntegrationTest.js @@ -34,7 +34,7 @@ describe("TokenUpdate", function () { const metadataKey = PrivateKey.generateED25519(); const newMetadataKey = PrivateKey.generateED25519(); const metadata = new Uint8Array(1); - const newMetadata = new Uint8Array(2) + const newMetadata = new Uint8Array(2); const response = await new TokenCreateTransaction() .setTokenName("ffff") From f45920bf61c3da2d6da622712920671e00127401 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Mon, 25 Mar 2024 16:34:49 +0200 Subject: [PATCH 07/30] update: example Signed-off-by: svetoslav-nikol0v --- examples/update-nfts-metadata.js | 91 ++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 21 deletions(-) diff --git a/examples/update-nfts-metadata.js b/examples/update-nfts-metadata.js index fc4fb8ed8..6be8040d0 100644 --- a/examples/update-nfts-metadata.js +++ b/examples/update-nfts-metadata.js @@ -1,4 +1,4 @@ -import { TokenCreateTransaction, TokenInfoQuery, TokenType, PrivateKey, Client, AccountId, TokenMintTransaction, TokenNftsUpdateTransaction } from "@hashgraph/sdk"; +import { TokenCreateTransaction, TokenInfoQuery, TokenType, PrivateKey, Client, AccountId, TokenMintTransaction, TokenNftsUpdateTransaction, TokenNftInfoQuery, NftId, AccountCreateTransaction, Hbar, TransferTransaction, TokenAssociateTransaction } from "@hashgraph/sdk"; import dotenv from "dotenv"; dotenv.config(); @@ -18,34 +18,40 @@ async function main() { const operatorId = AccountId.fromString(process.env.OPERATOR_ID); const operatorKey = PrivateKey.fromStringDer(process.env.OPERATOR_KEY); - const network = process.env.HEDERA_NETWORK + const network = process.env.HEDERA_NETWORK; const client = Client.forName(network).setOperator(operatorId, operatorKey); - const metadataKey = PrivateKey.generateECDSA() - console.log(`Generated metadata key: ${metadataKey.toString()}`); - // Set initial metadate - const metadata = new Uint8Array([1]) - // Set updated metadate - const updatedMetadata = new Uint8Array([1, 2]) + // Generate a metadata key + const metadataKey = PrivateKey.generateECDSA(); + // Initial metadata + const metadata = new Uint8Array([1]); + // New metadata + const newMetadata = new Uint8Array([1, 2]); + + let tokenNftsInfo, nftInfo; try { - // Create token + // Create a non fungible token collection with a metadata key set let createTokenTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") + .setMetadata(metadata) .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) .setAdminKey(operatorKey) .setTreasuryAccountId(operatorId) .setSupplyKey(operatorKey) .setMetadataKey(metadataKey) - .freezeWith(client) + .freezeWith(client); + + // Sign and execute create token transaction + const tokenCreateResponse = await (await createTokenTx.sign(operatorKey)).execute(client); - const tokenCreateResponse = await (await createTokenTx.sign(operatorKey)).execute(client) // Get receipt for create token transaction const tokenCreateReceipt = await tokenCreateResponse.getReceipt(client); console.log(`Status of token create transction: ${tokenCreateReceipt.status.toString()}`); + // Get token id const tokenId = tokenCreateReceipt.tokenId; console.log(`Token id: ${tokenId.toString()}`); @@ -59,25 +65,68 @@ async function main() { const tokenMintTx = new TokenMintTransaction() .setMetadata([metadata]) .setTokenId(tokenId) - console.log(`Set metadata: ${tokenMintTx.metadata}`); + .freezeWith(client); - const tokenMintResponse = await tokenMintTx.execute(client); - // Get receipt for mint token transaction + const tokenMintResponse = await(await tokenMintTx.sign(operatorKey)).execute(client); const tokenMintReceipt = await tokenMintResponse.getReceipt(client); console.log(`Status of token mint transction: ${tokenMintReceipt.status.toString()}`); + const nftSerial = tokenMintReceipt.serials[0]; + + // Get TokenNftInfo to show the metadata on the NFT created + tokenNftsInfo = await new TokenNftInfoQuery() + .setNftId(new NftId(tokenId, nftSerial)) + .execute(client); + nftInfo = tokenNftsInfo[0]; + console.log(`Set token NFT metadata:`, nftInfo.metadata); + + // Create an account to transfer the NFT to + const accountCreateTx = new AccountCreateTransaction() + .setKey(operatorKey) + .setMaxAutomaticTokenAssociations(10) + .setInitialBalance(new Hbar(100)) + .freezeWith(client); + + const accountCreateTxResponse = await(await accountCreateTx.sign(operatorKey)).execute(client); + const accountCreateTxReceipt = await accountCreateTxResponse.getReceipt(client); + const newAccountId = accountCreateTxReceipt.accountId; + console.log(`New account id: ${newAccountId.toString()}`); + + const tokenAssociateTx = new TokenAssociateTransaction() + .setAccountId(newAccountId) + .setTokenIds([tokenId]) + .freezeWith(client) + + const tokenAssociateTxResponse = await(await tokenAssociateTx.sign(operatorKey)).execute(client); + const tokenAssociateTxReceipt = await tokenAssociateTxResponse.getReceipt(client); + console.log(`Status of token associate transaction: ${tokenAssociateTxReceipt.status.toString()}`); + + // Transfer nft to the new account + const transferNftTx = new TransferTransaction() + .addNftTransfer(tokenId, nftSerial, operatorId, newAccountId) + .freezeWith(client); + + const transferNftTxResponse = await(await transferNftTx.sign(operatorKey)).execute(client); + const transferNftTxReceipt = await transferNftTxResponse.getReceipt(client); + console.log(`Status of transfer NFT transaction: ${transferNftTxReceipt.status.toString()}`); + // Update nfts metadata const tokenUpdateNftsTx = new TokenNftsUpdateTransaction() .setTokenId(tokenId) - .setSerialNumbers(tokenMintReceipt.serials) - .setMetadata(updatedMetadata) - .freezeWith(client) - console.log(`Updateted metadata: ${tokenUpdateNftsTx.metadata}`); + .setSerialNumbers([nftSerial]) + .setMetadata(newMetadata) + .freezeWith(client); - const tokenUpdateNftsResponse = await(await tokenUpdateNftsTx.sign(metadataKey)).execute(client) - // Get receipt for update nfts metadata transaction + const tokenUpdateNftsResponse = await(await tokenUpdateNftsTx.sign(metadataKey)).execute(client); const tokenUpdateNftsReceipt = await tokenUpdateNftsResponse.getReceipt(client); - console.log(`Status of token update bfts metadata transction: ${tokenUpdateNftsReceipt.status.toString()}`); + console.log(`Status of token update nfts transction: ${tokenUpdateNftsReceipt.status.toString()}`); + + // Get token nfts info in order to show the metadata on the NFT created + tokenNftsInfo = await new TokenNftInfoQuery() + .setNftId(new NftId(tokenId, nftSerial)) + .execute(client); + nftInfo = tokenNftsInfo[0]; + console.log(`Updated token NFT metadata:`, nftInfo.metadata); } catch(error){ console.log(error); } From 2ef1d8973485d66a01266188bd7b7f1b01ac18e8 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Mon, 25 Mar 2024 16:36:44 +0200 Subject: [PATCH 08/30] update: integration tests Signed-off-by: svetoslav-nikol0v --- test/integration/TokenInfoIntegrationTest.js | 4 + ...kenNftsUpdateTransactionIntegrationTest.js | 220 ++++++++++++++---- 2 files changed, 176 insertions(+), 48 deletions(-) diff --git a/test/integration/TokenInfoIntegrationTest.js b/test/integration/TokenInfoIntegrationTest.js index 389994a2c..2bf94d1d9 100644 --- a/test/integration/TokenInfoIntegrationTest.js +++ b/test/integration/TokenInfoIntegrationTest.js @@ -22,6 +22,7 @@ describe("TokenInfo", function () { const key2 = PrivateKey.generateED25519(); const key3 = PrivateKey.generateED25519(); const key4 = PrivateKey.generateED25519(); + const key5 = PrivateKey.generateED25519(); const response = await new TokenCreateTransaction() .setTokenName("ffff") @@ -34,6 +35,7 @@ describe("TokenInfo", function () { .setFreezeKey(key2) .setWipeKey(key3) .setSupplyKey(key4) + .setMetadataKey(key5) .setFreezeDefault(false) .execute(env.client); @@ -56,6 +58,7 @@ describe("TokenInfo", function () { expect(info.freezeKey.toString()).to.eql(key2.publicKey.toString()); expect(info.wipeKey.toString()).to.eql(key3.publicKey.toString()); expect(info.supplyKey.toString()).to.eql(key4.publicKey.toString()); + expect(info.metadataKey.toString()).to.eql(key5.publicKey.toString()); expect(info.defaultFreezeStatus).to.be.false; expect(info.defaultKycStatus).to.be.false; expect(info.isDeleted).to.be.false; @@ -94,6 +97,7 @@ describe("TokenInfo", function () { expect(info.freezeKey).to.be.null; expect(info.wipeKey).to.be.null; expect(info.supplyKey).to.be.null; + expect(info.metadataKey).to.be.null; expect(info.defaultFreezeStatus).to.be.null; expect(info.defaultKycStatus).to.be.null; expect(info.isDeleted).to.be.false; diff --git a/test/integration/TokenNftsUpdateTransactionIntegrationTest.js b/test/integration/TokenNftsUpdateTransactionIntegrationTest.js index 55541e1bd..c05c78075 100644 --- a/test/integration/TokenNftsUpdateTransactionIntegrationTest.js +++ b/test/integration/TokenNftsUpdateTransactionIntegrationTest.js @@ -7,85 +7,112 @@ import { TransactionResponse, TokenMintTransaction, TokenNftsUpdateTransaction, - TokenId, - TokenInfo, + Status, + TokenNftInfoQuery, + NftId, + TokenNftInfo, } from "../../src/exports.js"; import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js"; describe("TokenNftsUpdateTransaction", function () { - let client, operatorId, operatorKey; + let client, + operatorId, + operatorKey, + metadata, + newMetadata, + metadataKey, + tokenName, + tokenSymbol, + supplyKey, + tokenNftsInfo, + nftInfo, + wrongMetadataKey; before(async function () { const env = await IntegrationTestEnv.new(); client = env.client; operatorId = env.operatorId; operatorKey = env.operatorKey; + metadata = new Uint8Array([1]); + newMetadata = new Uint8Array([1, 2]); + metadataKey = PrivateKey.generateECDSA(); + supplyKey = PrivateKey.generateECDSA(); + tokenName = "Test"; + tokenSymbol = "T"; + wrongMetadataKey = PrivateKey.generateECDSA(); }); - it("should update the inital metadata of nfts", async function () { - const metadataKey = PrivateKey.generateECDSA(); - const metadata = new Uint8Array(1); - const newMetadata = new Uint8Array(2); - + it("should update the NFT metadata", async function () { + this.timeout(120000); try { - let createTokenTx = new TokenCreateTransaction() - .setTokenName("Test") - .setTokenSymbol("T") - .setTokenType(TokenType.NonFungibleUnique) - .setTreasuryAccountId(operatorId) + const createTokenTx = new TokenCreateTransaction() + .setTokenName(tokenName) + .setTokenSymbol(tokenSymbol) + .setMetadata(metadata) .setAdminKey(operatorKey) - .setTreasuryAccountId(operatorId) - .setSupplyKey(operatorKey) + .setSupplyKey(supplyKey) .setMetadataKey(metadataKey) - .freezeWith(client); - expect(createTokenTx.tokenName).to.be.equal("Test"); - expect(createTokenTx.tokenSymbol).to.be.equal("T"); - expect(createTokenTx.tokenType).to.be.equal( - TokenType.NonFungibleUnique, + .setTreasuryAccountId(operatorId) + .setTokenType(TokenType.NonFungibleUnique); + expect(createTokenTx.tokenName).to.be.eql(tokenName); + expect(createTokenTx.tokenSymbol).to.be.eql(tokenSymbol); + expect(createTokenTx.metadata).to.be.eql(metadata); + expect(createTokenTx.metadataKey.toString()).to.be.eql( + metadataKey.toString(), ); - expect(createTokenTx.treasuryAccountId.toString()).to.be.equal( + expect(createTokenTx.treasuryAccountId.toString()).to.be.eql( operatorId.toString(), ); - expect(createTokenTx.adminKey.toString()).to.be.equal( - operatorKey.toString(), + expect(createTokenTx.tokenType).to.be.eql( + TokenType.NonFungibleUnique, ); - expect(createTokenTx.supplyKey.toString()).to.be.equal( + expect(createTokenTx.adminKey.toString()).to.be.eql( operatorKey.toString(), ); - expect(createTokenTx.metadataKey.toString()).to.be.equal( - metadataKey.toString(), + expect(createTokenTx.supplyKey.toString()).to.be.eql( + supplyKey.toString(), ); - const createTokenResponse = await ( - await createTokenTx.sign(operatorKey) - ).execute(client); - expect(createTokenResponse).to.be.instanceof(TransactionResponse); - - const createTokenReceipt = - await createTokenResponse.getReceipt(client); - expect(createTokenReceipt).to.be.instanceof(TransactionReceipt); - - const tokenId = createTokenReceipt.tokenId; - expect(tokenId).to.be.instanceof(TokenId); + const createTokenTxResponse = await createTokenTx.execute(client); + expect(createTokenTxResponse).to.be.instanceof(TransactionResponse); + const createTokenTxReceipt = + await createTokenTxResponse.getReceipt(client); + expect(createTokenTxReceipt).to.be.instanceof(TransactionReceipt); + expect(createTokenTxReceipt.status).to.be.eql(Status.Success); + const tokenId = createTokenTxReceipt.tokenId; + expect(tokenId).to.not.be.null; const tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(client); - expect(tokenInfo).to.be.instanceof(TokenInfo); + expect(tokenInfo.metadata).to.be.eql(metadata); const tokenMintTx = new TokenMintTransaction() .setMetadata([metadata]) - .setTokenId(tokenId); + .setTokenId(tokenId) + .freezeWith(client); - const tokenMintResponse = await tokenMintTx.execute(client); + const tokenMintResponse = await ( + await tokenMintTx.sign(supplyKey) + ).execute(client); expect(tokenMintResponse).to.be.instanceof(TransactionResponse); - const tokenMintReceipt = await tokenMintResponse.getReceipt(client); expect(tokenMintReceipt).to.be.instanceof(TransactionReceipt); + expect(tokenMintReceipt.status).to.be.eql(Status.Success); + + const nftSerial = tokenMintReceipt.serials[0]; + const nftId = new NftId(tokenId, nftSerial); + + tokenNftsInfo = await new TokenNftInfoQuery() + .setNftId(nftId) + .execute(client); + nftInfo = tokenNftsInfo[0]; + expect(nftInfo).to.be.instanceof(TokenNftInfo); + expect(nftInfo.metadata).to.be.eql(metadata); const tokenUpdateNftsTx = new TokenNftsUpdateTransaction() .setTokenId(tokenId) - .setSerialNumbers(tokenMintReceipt.serials) + .setSerialNumbers([nftSerial]) .setMetadata(newMetadata) .freezeWith(client); @@ -95,17 +122,114 @@ describe("TokenNftsUpdateTransaction", function () { expect(tokenUpdateNftsResponse).to.be.instanceof( TransactionResponse, ); - const tokenUpdateNftsReceipt = await tokenUpdateNftsResponse.getReceipt(client); expect(tokenUpdateNftsReceipt).to.be.instanceof(TransactionReceipt); + expect(tokenUpdateNftsReceipt.status).to.be.eql(Status.Success); + + tokenNftsInfo = await new TokenNftInfoQuery() + .setNftId(new NftId(tokenId, nftSerial)) + .execute(client); + nftInfo = tokenNftsInfo[0]; + expect(nftInfo.metadata).to.be.eql(newMetadata); } catch (error) { - console.log(error); + console.warn(error); } }); - it("should return INVALID_METADATA_KEY error", async function () {}); - it("should return TOKEN_HAS_NO_METADATA_KEY error", async function () {}); - it("should return MISSING_TOKEN_METADATA error", async function () {}); - it("should return MISSING_SERIAL_NUMBERS error", async function () {}); + it("cannot update the NFT metadata if the metadataKey is missing", async function () { + this.timeout(120000); + try { + const createTokenTx = new TokenCreateTransaction() + .setTokenName(tokenName) + .setTokenSymbol(tokenSymbol) + .setMetadata(metadata) + .setAdminKey(operatorKey) + .setSupplyKey(supplyKey) + .setTreasuryAccountId(operatorId) + .setTokenType(TokenType.NonFungibleUnique); + + const createTokenTxResponse = await createTokenTx.execute(client); + const createTokenTxReceipt = + await createTokenTxResponse.getReceipt(client); + const tokenId = createTokenTxReceipt.tokenId; + + const tokenMintTx = new TokenMintTransaction() + .setMetadata([metadata]) + .setTokenId(tokenId) + .freezeWith(client); + + const tokenMintResponse = await ( + await tokenMintTx.sign(supplyKey) + ).execute(client); + const tokenMintReceipt = await tokenMintResponse.getReceipt(client); + + const nftSerial = tokenMintReceipt.serials[0]; + const nftId = new NftId(tokenId, nftSerial); + + tokenNftsInfo = await new TokenNftInfoQuery() + .setNftId(nftId) + .execute(client); + nftInfo = tokenNftsInfo[0]; + + const tokenUpdateNftsTx = new TokenNftsUpdateTransaction() + .setTokenId(tokenId) + .setSerialNumbers([nftSerial]) + .setMetadata(newMetadata) + .freezeWith(client); + + const tokenUpdateTxResponse = await ( + await tokenUpdateNftsTx.sign(metadataKey) + ).execute(client); + await tokenUpdateTxResponse.getReceipt(client); + } catch (error) { + expect(error.status).to.be.eql(Status.TokenHasNoMetadataKey); + } + }); + + it("cannot update the NFT metadata when the transaction is not signed with metadataKey", async function () { + this.timeout(120000); + try { + const createTokenTx = new TokenCreateTransaction() + .setTokenName(tokenName) + .setTokenSymbol(tokenSymbol) + .setMetadata(metadata) + .setAdminKey(operatorKey) + .setMetadataKey(metadataKey) + .setSupplyKey(supplyKey) + .setTreasuryAccountId(operatorId) + .setTokenType(TokenType.NonFungibleUnique); + + const createTokenTxResponse = await createTokenTx.execute(client); + const createTokenTxReceipt = + await createTokenTxResponse.getReceipt(client); + const tokenId = createTokenTxReceipt.tokenId; + + const tokenMintTx = new TokenMintTransaction() + .setMetadata([metadata]) + .setTokenId(tokenId) + .freezeWith(client); + + const tokenMintResponse = await ( + await tokenMintTx.sign(supplyKey) + ).execute(client); + const tokenMintReceipt = await tokenMintResponse.getReceipt(client); + + const nftSerial = tokenMintReceipt.serials[0]; + + const tokenUpdateNftsTx = new TokenNftsUpdateTransaction() + .setTokenId(tokenId) + .setSerialNumbers([nftSerial]) + .setMetadata(newMetadata) + .freezeWith(client); + + await ( + await ( + await tokenUpdateNftsTx.sign(wrongMetadataKey) + ).execute(client) + ).getReceipt(client); + } catch (error) { + expect(error.status).to.be.eql(Status.InvalidSignature); + } + }); }); From 2b19450534bc3efc4e051d9712203ab2267c81e2 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Tue, 26 Mar 2024 17:07:36 +0200 Subject: [PATCH 09/30] update: update examples Signed-off-by: svetoslav-nikol0v --- examples/update-nfts-metadata.js | 25 +++++---- examples/update-token-metadata.js | 87 +++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 examples/update-token-metadata.js diff --git a/examples/update-nfts-metadata.js b/examples/update-nfts-metadata.js index 6be8040d0..4c47d3107 100644 --- a/examples/update-nfts-metadata.js +++ b/examples/update-nfts-metadata.js @@ -31,11 +31,10 @@ async function main() { let tokenNftsInfo, nftInfo; try { - // Create a non fungible token collection with a metadata key set + // Create a non fungible token let createTokenTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") - .setMetadata(metadata) .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) .setAdminKey(operatorKey) @@ -45,14 +44,14 @@ async function main() { .freezeWith(client); // Sign and execute create token transaction - const tokenCreateResponse = await (await createTokenTx.sign(operatorKey)).execute(client); + const tokenCreateTxResponse = await (await createTokenTx.sign(operatorKey)).execute(client); // Get receipt for create token transaction - const tokenCreateReceipt = await tokenCreateResponse.getReceipt(client); - console.log(`Status of token create transction: ${tokenCreateReceipt.status.toString()}`); + const tokenCreateTxReceipt = await tokenCreateTxResponse.getReceipt(client); + console.log(`Status of token create transction: ${tokenCreateTxReceipt.status.toString()}`); // Get token id - const tokenId = tokenCreateReceipt.tokenId; + const tokenId = tokenCreateTxReceipt.tokenId; console.log(`Token id: ${tokenId.toString()}`); // Get token info @@ -67,11 +66,11 @@ async function main() { .setTokenId(tokenId) .freezeWith(client); - const tokenMintResponse = await(await tokenMintTx.sign(operatorKey)).execute(client); - const tokenMintReceipt = await tokenMintResponse.getReceipt(client); - console.log(`Status of token mint transction: ${tokenMintReceipt.status.toString()}`); + const tokenMintTxResponse = await(await tokenMintTx.sign(operatorKey)).execute(client); + const tokenMintTxReceipt = await tokenMintTxResponse.getReceipt(client); + console.log(`Status of token mint transction: ${tokenMintTxReceipt.status.toString()}`); - const nftSerial = tokenMintReceipt.serials[0]; + const nftSerial = tokenMintTxReceipt.serials[0]; // Get TokenNftInfo to show the metadata on the NFT created tokenNftsInfo = await new TokenNftInfoQuery() @@ -117,9 +116,9 @@ async function main() { .setMetadata(newMetadata) .freezeWith(client); - const tokenUpdateNftsResponse = await(await tokenUpdateNftsTx.sign(metadataKey)).execute(client); - const tokenUpdateNftsReceipt = await tokenUpdateNftsResponse.getReceipt(client); - console.log(`Status of token update nfts transction: ${tokenUpdateNftsReceipt.status.toString()}`); + const tokenUpdateNftsTxResponse = await(await tokenUpdateNftsTx.sign(metadataKey)).execute(client); + const tokenUpdateNftsTxReceipt = await tokenUpdateNftsTxResponse.getReceipt(client); + console.log(`Status of token update nfts transction: ${tokenUpdateNftsTxReceipt.status.toString()}`); // Get token nfts info in order to show the metadata on the NFT created tokenNftsInfo = await new TokenNftInfoQuery() diff --git a/examples/update-token-metadata.js b/examples/update-token-metadata.js new file mode 100644 index 000000000..7d2450053 --- /dev/null +++ b/examples/update-token-metadata.js @@ -0,0 +1,87 @@ +import { TokenCreateTransaction, TokenInfoQuery, TokenType, PrivateKey, Client, AccountId, TokenUpdateTransaction } from "@hashgraph/sdk"; +import dotenv from "dotenv"; + +dotenv.config(); + +/** + * @notice E2E-HIP-657 + * @url https://hips.hedera.com/hip/hip-657 + */ +async function main() { + if ( + !process.env.OPERATOR_KEY || + !process.env.OPERATOR_ID || + !process.env.HEDERA_NETWORK + ) { + throw new Error("Please set required keys in .env file."); + } + + const operatorId = AccountId.fromString(process.env.OPERATOR_ID); + const operatorKey = PrivateKey.fromStringDer(process.env.OPERATOR_KEY); + const network = process.env.HEDERA_NETWORK; + const client = Client.forName(network).setOperator(operatorId, operatorKey); + + // Generate a metadata key + const metadataKey = PrivateKey.generateECDSA(); + // Initial metadata + const metadata = new Uint8Array([1]); + // New metadata + const newMetadata = new Uint8Array([1, 2]); + + let tokenInfo; + + try { + // Create a non fungible token + let createTokenTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setMetadata(metadata) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setTreasuryAccountId(operatorId) + .setSupplyKey(operatorKey) + .setMetadataKey(metadataKey) + .freezeWith(client); + + // Sign and execute create token transaction + const tokenCreateTxResponse = await (await createTokenTx.sign(operatorKey)).execute(client); + + // Get receipt for create token transaction + const tokenCreateTxReceipt = await tokenCreateTxResponse.getReceipt(client); + console.log(`Status of token create transction: ${tokenCreateTxReceipt.status.toString()}`); + + // Get token id + const tokenId = tokenCreateTxReceipt.tokenId; + console.log(`Token id: ${tokenId.toString()}`); + + // Get token info + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(client); + console.log(`Token metadata:`, tokenInfo.metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(client); + + // Sign transactions with metadata key and execute it + const tokenUpdateTxResponse = await (await tokenUpdateTx.sign(metadataKey)).execute(client); + + // Get receipt for token update transaction + const tokenUpdateTxReceipt = await tokenUpdateTxResponse.getReceipt(client); + console.log(`Status of token update transction: ${tokenUpdateTxReceipt.status.toString()}`); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(client); + console.log(`Token updated metadata:`, tokenInfo.metadata); + } catch(error){ + console.log(error); + } + + client.close() +} + +void main(); From 8b2bb707fa5cbf15606e208170f4c42b2be1224f Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Tue, 26 Mar 2024 17:08:11 +0200 Subject: [PATCH 10/30] update: adding all integration tests Signed-off-by: svetoslav-nikol0v --- src/token/TokenNftsUpdateTransaction.js | 33 +- .../integration/TokenCreateIntegrationTest.js | 6 - ...kenNftsUpdateTransactionIntegrationTest.js | 356 ++++++++++++------ .../integration/TokenUpdateIntegrationTest.js | 249 +++++++++++- 4 files changed, 488 insertions(+), 156 deletions(-) diff --git a/src/token/TokenNftsUpdateTransaction.js b/src/token/TokenNftsUpdateTransaction.js index 28a334ed0..0827d3638 100644 --- a/src/token/TokenNftsUpdateTransaction.js +++ b/src/token/TokenNftsUpdateTransaction.js @@ -132,14 +132,6 @@ export default class TokenNftsUpdateTransaction extends Transaction { ); } - /** - * @description Extract the token id. Returns the token id. - * @returns {?TokenId} - */ - get tokenId() { - return this._tokenId; - } - /** * @description Assign the token id. * @param {TokenId | string} tokenId @@ -155,14 +147,6 @@ export default class TokenNftsUpdateTransaction extends Transaction { return this; } - /** - * @description Extract the list of serial numbers. Returns the list of serial numbers. - * @returns {?Long[]} - */ - get serialNumbers() { - return this._serialNumbers; - } - /** * @description Assign the list of serial numbers. * @param {Long[]} serialNumbers @@ -175,13 +159,6 @@ export default class TokenNftsUpdateTransaction extends Transaction { return this; } - /** - * @returns {?Uint8Array} - */ - get metadata() { - return this._metadata; - } - /** * @param {Uint8Array} metadata * @returns {this} @@ -232,9 +209,13 @@ export default class TokenNftsUpdateTransaction extends Transaction { token: this._tokenId != null ? this._tokenId._toProtobuf() : null, serialNumbers: this._serialNumbers != null ? this._serialNumbers : [], - metadata: { - value: this._metadata != null ? this._metadata : null, - }, + ...(this._metadata != null + ? { + metadata: { + value: this._metadata, + }, + } + : null), }; } diff --git a/test/integration/TokenCreateIntegrationTest.js b/test/integration/TokenCreateIntegrationTest.js index abf248a1c..fd50af46b 100644 --- a/test/integration/TokenCreateIntegrationTest.js +++ b/test/integration/TokenCreateIntegrationTest.js @@ -23,8 +23,6 @@ describe("TokenCreate", function () { const key2 = PrivateKey.generateED25519(); const key3 = PrivateKey.generateED25519(); const key4 = PrivateKey.generateED25519(); - const metadataKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array(1); const response = await new TokenCreateTransaction() .setTokenName("ffff") @@ -38,8 +36,6 @@ describe("TokenCreate", function () { .setWipeKey(key3) .setSupplyKey(key4) .setFreezeDefault(false) - .setMetadataKey(metadataKey) - .setMetadata(metadata) .execute(env.client); const tokenId = (await response.getReceipt(env.client)).tokenId; @@ -67,8 +63,6 @@ describe("TokenCreate", function () { expect(info.autoRenewAccountId).to.be.null; expect(info.autoRenewPeriod).to.be.null; expect(info.expirationTime).to.be.not.null; - expect(info.metadataKey).to.eql(metadataKey.toString()); - expect(info.metadata).to.eql(metadata); }); it("should be executable with minimal properties set", async function () { diff --git a/test/integration/TokenNftsUpdateTransactionIntegrationTest.js b/test/integration/TokenNftsUpdateTransactionIntegrationTest.js index c05c78075..0c5767b15 100644 --- a/test/integration/TokenNftsUpdateTransactionIntegrationTest.js +++ b/test/integration/TokenNftsUpdateTransactionIntegrationTest.js @@ -1,16 +1,12 @@ import { TokenCreateTransaction, - TokenInfoQuery, TokenType, PrivateKey, - TransactionReceipt, - TransactionResponse, TokenMintTransaction, TokenNftsUpdateTransaction, - Status, TokenNftInfoQuery, NftId, - TokenNftInfo, + Status, } from "../../src/exports.js"; import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js"; @@ -24,9 +20,8 @@ describe("TokenNftsUpdateTransaction", function () { tokenName, tokenSymbol, supplyKey, - tokenNftsInfo, - nftInfo, - wrongMetadataKey; + wrongMetadataKey, + nftCount; before(async function () { const env = await IntegrationTestEnv.new(); @@ -40,110 +35,230 @@ describe("TokenNftsUpdateTransaction", function () { tokenName = "Test"; tokenSymbol = "T"; wrongMetadataKey = PrivateKey.generateECDSA(); + nftCount = 4; }); - it("should update the NFT metadata", async function () { + it("should update the metadata of entire NFT collection", async function () { this.timeout(120000); - try { - const createTokenTx = new TokenCreateTransaction() - .setTokenName(tokenName) - .setTokenSymbol(tokenSymbol) - .setMetadata(metadata) - .setAdminKey(operatorKey) - .setSupplyKey(supplyKey) - .setMetadataKey(metadataKey) - .setTreasuryAccountId(operatorId) - .setTokenType(TokenType.NonFungibleUnique); - expect(createTokenTx.tokenName).to.be.eql(tokenName); - expect(createTokenTx.tokenSymbol).to.be.eql(tokenSymbol); - expect(createTokenTx.metadata).to.be.eql(metadata); - expect(createTokenTx.metadataKey.toString()).to.be.eql( - metadataKey.toString(), - ); - expect(createTokenTx.treasuryAccountId.toString()).to.be.eql( - operatorId.toString(), - ); - expect(createTokenTx.tokenType).to.be.eql( - TokenType.NonFungibleUnique, - ); - expect(createTokenTx.adminKey.toString()).to.be.eql( - operatorKey.toString(), - ); - expect(createTokenTx.supplyKey.toString()).to.be.eql( - supplyKey.toString(), - ); - const createTokenTxResponse = await createTokenTx.execute(client); - expect(createTokenTxResponse).to.be.instanceof(TransactionResponse); - const createTokenTxReceipt = - await createTokenTxResponse.getReceipt(client); - expect(createTokenTxReceipt).to.be.instanceof(TransactionReceipt); - expect(createTokenTxReceipt.status).to.be.eql(Status.Success); - const tokenId = createTokenTxReceipt.tokenId; - expect(tokenId).to.not.be.null; + const createTokenTx = new TokenCreateTransaction() + .setTokenName(tokenName) + .setTokenSymbol(tokenSymbol) + .setAdminKey(operatorKey) + .setSupplyKey(supplyKey) + .setMetadataKey(metadataKey) + .setTreasuryAccountId(operatorId) + .setTokenType(TokenType.NonFungibleUnique); - const tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(client); - expect(tokenInfo.metadata).to.be.eql(metadata); + const createTokenTxResponse = await createTokenTx.execute(client); + const createTokenTxReceipt = + await createTokenTxResponse.getReceipt(client); + const tokenId = createTokenTxReceipt.tokenId; - const tokenMintTx = new TokenMintTransaction() - .setMetadata([metadata]) - .setTokenId(tokenId) - .freezeWith(client); + const tokenMintTx = new TokenMintTransaction() + .setMetadata(generateMetadataList(metadata, nftCount)) + .setTokenId(tokenId) + .freezeWith(client); - const tokenMintResponse = await ( - await tokenMintTx.sign(supplyKey) - ).execute(client); - expect(tokenMintResponse).to.be.instanceof(TransactionResponse); - const tokenMintReceipt = await tokenMintResponse.getReceipt(client); - expect(tokenMintReceipt).to.be.instanceof(TransactionReceipt); - expect(tokenMintReceipt.status).to.be.eql(Status.Success); + const tokenMintResponse = await ( + await tokenMintTx.sign(supplyKey) + ).execute(client); + const tokenMintReceipt = await tokenMintResponse.getReceipt(client); + const serials = tokenMintReceipt.serials; - const nftSerial = tokenMintReceipt.serials[0]; - const nftId = new NftId(tokenId, nftSerial); + const metadatas = await geNftsMetadata(client, tokenId, serials); + expect( + metadatas.every( + (mt) => mt === Buffer.from(metadata).toString("hex"), + ), + ).to.be.true; - tokenNftsInfo = await new TokenNftInfoQuery() - .setNftId(nftId) - .execute(client); - nftInfo = tokenNftsInfo[0]; - expect(nftInfo).to.be.instanceof(TokenNftInfo); - expect(nftInfo.metadata).to.be.eql(metadata); + await ( + await ( + await new TokenNftsUpdateTransaction() + .setTokenId(tokenId) + .setSerialNumbers(serials) + .setMetadata(newMetadata) + .freezeWith(client) + .sign(metadataKey) + ).execute(client) + ).getReceipt(client); - const tokenUpdateNftsTx = new TokenNftsUpdateTransaction() - .setTokenId(tokenId) - .setSerialNumbers([nftSerial]) - .setMetadata(newMetadata) - .freezeWith(client); + const newMetadatas = await geNftsMetadata(client, tokenId, serials); + expect( + newMetadatas.every( + (mt) => mt === Buffer.from(newMetadata).toString("hex"), + ), + ).to.be.true; + }); - const tokenUpdateNftsResponse = await ( - await tokenUpdateNftsTx.sign(metadataKey) - ).execute(client); - expect(tokenUpdateNftsResponse).to.be.instanceof( - TransactionResponse, - ); - const tokenUpdateNftsReceipt = - await tokenUpdateNftsResponse.getReceipt(client); - expect(tokenUpdateNftsReceipt).to.be.instanceof(TransactionReceipt); - expect(tokenUpdateNftsReceipt.status).to.be.eql(Status.Success); - - tokenNftsInfo = await new TokenNftInfoQuery() - .setNftId(new NftId(tokenId, nftSerial)) - .execute(client); - nftInfo = tokenNftsInfo[0]; - expect(nftInfo.metadata).to.be.eql(newMetadata); - } catch (error) { - console.warn(error); - } + it("should update the NFT's metadata", async function () { + this.timeout(120000); + + const createTokenTx = new TokenCreateTransaction() + .setTokenName(tokenName) + .setTokenSymbol(tokenSymbol) + .setAdminKey(operatorKey) + .setSupplyKey(supplyKey) + .setMetadataKey(metadataKey) + .setTreasuryAccountId(operatorId) + .setTokenType(TokenType.NonFungibleUnique); + + const createTokenTxResponse = await createTokenTx.execute(client); + const createTokenTxReceipt = + await createTokenTxResponse.getReceipt(client); + const tokenId = createTokenTxReceipt.tokenId; + + const tokenMintTx = new TokenMintTransaction() + .setMetadata(generateMetadataList(metadata, nftCount)) + .setTokenId(tokenId) + .freezeWith(client); + + const tokenMintResponse = await ( + await tokenMintTx.sign(supplyKey) + ).execute(client); + const tokenMintReceipt = await tokenMintResponse.getReceipt(client); + const serials = tokenMintReceipt.serials; + + const metadatas = await geNftsMetadata(client, tokenId, serials); + expect( + metadatas.every( + (mt) => mt === Buffer.from(metadata).toString("hex"), + ), + ).to.be.true; + + await ( + await ( + await new TokenNftsUpdateTransaction() + .setTokenId(tokenId) + .setSerialNumbers([serials[0], serials[1]]) + .setMetadata(newMetadata) + .freezeWith(client) + .sign(metadataKey) + ).execute(client) + ).getReceipt(client); + + const newMetadatas = await geNftsMetadata(client, tokenId, serials); + expect( + newMetadatas.map( + (mt) => mt === Buffer.from(newMetadata).toString("hex"), + ), + ).to.deep.eql([true, true, false, false]); }); - it("cannot update the NFT metadata if the metadataKey is missing", async function () { + it("should NOT update the NFT's metadata", async function () { + this.timeout(120000); + + const createTokenTx = new TokenCreateTransaction() + .setTokenName(tokenName) + .setTokenSymbol(tokenSymbol) + .setAdminKey(operatorKey) + .setSupplyKey(supplyKey) + .setMetadataKey(metadataKey) + .setTreasuryAccountId(operatorId) + .setTokenType(TokenType.NonFungibleUnique); + + const createTokenTxResponse = await createTokenTx.execute(client); + const createTokenTxReceipt = + await createTokenTxResponse.getReceipt(client); + const tokenId = createTokenTxReceipt.tokenId; + + const tokenMintTx = new TokenMintTransaction() + .setMetadata(generateMetadataList(metadata, nftCount)) + .setTokenId(tokenId) + .freezeWith(client); + + const tokenMintResponse = await ( + await tokenMintTx.sign(supplyKey) + ).execute(client); + const tokenMintReceipt = await tokenMintResponse.getReceipt(client); + const serials = tokenMintReceipt.serials; + + const metadatas = await geNftsMetadata(client, tokenId, serials); + expect( + metadatas.every( + (mt) => mt === Buffer.from(metadata).toString("hex"), + ), + ).to.be.true; + + await ( + await ( + await new TokenNftsUpdateTransaction() + .setTokenId(tokenId) + .setSerialNumbers(serials) + .freezeWith(client) + .sign(metadataKey) + ).execute(client) + ).getReceipt(client); + + const sameMetadatas = await geNftsMetadata(client, tokenId, serials); + expect( + sameMetadatas.every( + (mt) => mt === Buffer.from(metadata).toString("hex"), + ), + ).to.be.true; + }); + + it("should earse the metadata of entire NFT collection", async function () { + this.timeout(120000); + + const createTokenTx = new TokenCreateTransaction() + .setTokenName(tokenName) + .setTokenSymbol(tokenSymbol) + .setAdminKey(operatorKey) + .setSupplyKey(supplyKey) + .setMetadataKey(metadataKey) + .setTreasuryAccountId(operatorId) + .setTokenType(TokenType.NonFungibleUnique); + + const createTokenTxResponse = await createTokenTx.execute(client); + const createTokenTxReceipt = + await createTokenTxResponse.getReceipt(client); + const tokenId = createTokenTxReceipt.tokenId; + + const tokenMintTx = new TokenMintTransaction() + .setMetadata(generateMetadataList(metadata, nftCount)) + .setTokenId(tokenId) + .freezeWith(client); + + const tokenMintResponse = await ( + await tokenMintTx.sign(supplyKey) + ).execute(client); + const tokenMintReceipt = await tokenMintResponse.getReceipt(client); + const serials = tokenMintReceipt.serials; + + const metadatas = await geNftsMetadata(client, tokenId, serials); + expect( + metadatas.every( + (mt) => mt === Buffer.from(metadata).toString("hex"), + ), + ).to.be.true; + + await ( + await ( + await new TokenNftsUpdateTransaction() + .setTokenId(tokenId) + .setMetadata([]) + .setSerialNumbers(serials) + .freezeWith(client) + .sign(metadataKey) + ).execute(client) + ).getReceipt(client); + + const sameMetadatas = await geNftsMetadata(client, tokenId, serials); + expect( + sameMetadatas.every( + (mt) => mt === Buffer.from(new Uint8Array()).toString("hex"), + ), + ).to.be.true; + }); + + it("should NOT update the NFTs metadata if the metadataKey is NOT set", async function () { this.timeout(120000); try { const createTokenTx = new TokenCreateTransaction() .setTokenName(tokenName) .setTokenSymbol(tokenSymbol) - .setMetadata(metadata) .setAdminKey(operatorKey) .setSupplyKey(supplyKey) .setTreasuryAccountId(operatorId) @@ -155,7 +270,7 @@ describe("TokenNftsUpdateTransaction", function () { const tokenId = createTokenTxReceipt.tokenId; const tokenMintTx = new TokenMintTransaction() - .setMetadata([metadata]) + .setMetadata(generateMetadataList(metadata, nftCount)) .setTokenId(tokenId) .freezeWith(client); @@ -164,36 +279,30 @@ describe("TokenNftsUpdateTransaction", function () { ).execute(client); const tokenMintReceipt = await tokenMintResponse.getReceipt(client); - const nftSerial = tokenMintReceipt.serials[0]; - const nftId = new NftId(tokenId, nftSerial); - - tokenNftsInfo = await new TokenNftInfoQuery() - .setNftId(nftId) - .execute(client); - nftInfo = tokenNftsInfo[0]; + const serials = tokenMintReceipt.serials; const tokenUpdateNftsTx = new TokenNftsUpdateTransaction() .setTokenId(tokenId) - .setSerialNumbers([nftSerial]) + .setSerialNumbers(serials) .setMetadata(newMetadata) .freezeWith(client); - const tokenUpdateTxResponse = await ( - await tokenUpdateNftsTx.sign(metadataKey) - ).execute(client); - await tokenUpdateTxResponse.getReceipt(client); + await ( + await ( + await tokenUpdateNftsTx.sign(metadataKey) + ).execute(client) + ).getReceipt(client); } catch (error) { expect(error.status).to.be.eql(Status.TokenHasNoMetadataKey); } }); - it("cannot update the NFT metadata when the transaction is not signed with metadataKey", async function () { + it("should NOT update the NFTs metadata when the transaction is not signed with the metadataKey", async function () { this.timeout(120000); try { const createTokenTx = new TokenCreateTransaction() .setTokenName(tokenName) .setTokenSymbol(tokenSymbol) - .setMetadata(metadata) .setAdminKey(operatorKey) .setMetadataKey(metadataKey) .setSupplyKey(supplyKey) @@ -206,7 +315,7 @@ describe("TokenNftsUpdateTransaction", function () { const tokenId = createTokenTxReceipt.tokenId; const tokenMintTx = new TokenMintTransaction() - .setMetadata([metadata]) + .setMetadata(generateMetadataList(metadata, nftCount)) .setTokenId(tokenId) .freezeWith(client); @@ -215,11 +324,11 @@ describe("TokenNftsUpdateTransaction", function () { ).execute(client); const tokenMintReceipt = await tokenMintResponse.getReceipt(client); - const nftSerial = tokenMintReceipt.serials[0]; + const serials = tokenMintReceipt.serials; const tokenUpdateNftsTx = new TokenNftsUpdateTransaction() .setTokenId(tokenId) - .setSerialNumbers([nftSerial]) + .setSerialNumbers(serials) .setMetadata(newMetadata) .freezeWith(client); @@ -233,3 +342,26 @@ describe("TokenNftsUpdateTransaction", function () { } }); }); + +function generateMetadataList(metadata, count) { + const list = []; + + for (let index = 0; index < count; index++) { + list.push(metadata); + } + return list; +} + +async function geNftsMetadata(client, tokenId, serials) { + const metadatas = []; + + for (let index = 0; index < serials.length; index++) { + const nftId = new NftId(tokenId, serials[index]); + const nftInfo = await new TokenNftInfoQuery() + .setNftId(nftId) + .execute(client); + metadatas.push(nftInfo[0].metadata.toString("hex")); + } + + return metadatas; +} diff --git a/test/integration/TokenUpdateIntegrationTest.js b/test/integration/TokenUpdateIntegrationTest.js index 29debd87e..ae65e4cff 100644 --- a/test/integration/TokenUpdateIntegrationTest.js +++ b/test/integration/TokenUpdateIntegrationTest.js @@ -31,10 +31,6 @@ describe("TokenUpdate", function () { const key3 = PrivateKey.generateED25519(); const key4 = PrivateKey.generateED25519(); const key5 = PrivateKey.generateED25519(); - const metadataKey = PrivateKey.generateED25519(); - const newMetadataKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array(1); - const newMetadata = new Uint8Array(2); const response = await new TokenCreateTransaction() .setTokenName("ffff") @@ -49,8 +45,6 @@ describe("TokenUpdate", function () { .setSupplyKey(key4) .setFreezeDefault(false) .setPauseKey(key5) - .setMetadataKey(metadataKey) - .setMetadata(metadata) .execute(env.client); const token = (await response.getReceipt(env.client)).tokenId; @@ -58,6 +52,11 @@ describe("TokenUpdate", function () { let info = await new TokenInfoQuery() .setTokenId(token) .execute(env.client); + + expect(info.tokenId.toString()).to.eql(token.toString()); + expect(info.name).to.eql("ffff"); + expect(info.symbol).to.eql("F"); + expect(info.decimals).to.eql(3); expect(info.totalSupply.toInt()).to.eql(1000000); expect(info.treasuryAccountId.toString()).to.be.equal( operatorId.toString(), @@ -74,16 +73,12 @@ describe("TokenUpdate", function () { expect(info.autoRenewAccountId).to.be.null; expect(info.autoRenewPeriod).to.be.null; expect(info.expirationTime).to.be.not.null; - expect(info.metadataKey.toString()).to.eql(metadataKey.toString()); - expect(info.metadata).to.eql(metadata); await ( await new TokenUpdateTransaction() .setTokenId(token) .setTokenName("aaaa") .setTokenSymbol("A") - .setMetadataKey(newMetadataKey) - .setMetadata(newMetadata) .execute(env.client) ).getReceipt(env.client); @@ -108,8 +103,6 @@ describe("TokenUpdate", function () { expect(info.autoRenewAccountId).to.be.null; expect(info.autoRenewPeriod).to.be.null; expect(info.expirationTime).to.be.not.null; - expect(info.metadataKey.toString()).to.eql(newMetadataKey.toString()); - expect(info.metadata).to.eql(newMetadata); }); it("should be able to update treasury", async function () { @@ -451,6 +444,238 @@ describe("TokenUpdate", function () { } }); + it("should update token metadata", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const operatorKey = env.operatorKey; + const metadataKey = PrivateKey.generateECDSA(); + const supplyKey = PrivateKey.generateECDSA(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + let tokeInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokeInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + ).getReceipt(env.client); + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokeInfo.metadata).to.eql(newMetadata); + }); + + it("should NOT update token metadata", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const operatorKey = env.operatorKey; + const metadataKey = PrivateKey.generateECDSA(); + const supplyKey = PrivateKey.generateECDSA(); + const metadata = new Uint8Array([1]); + let tokeInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokeInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + ).getReceipt(env.client); + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokeInfo.metadata).to.eql(metadata); + }); + + it("should earse token metadata", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const operatorKey = env.operatorKey; + const metadataKey = PrivateKey.generateECDSA(); + const supplyKey = PrivateKey.generateECDSA(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array(); + let tokeInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokeInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + ).getReceipt(env.client); + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokeInfo.metadata).to.eql(newMetadata); + }); + + /** @summary Currently the transaction passing even when the transaction is signed with wrong metadata key */ + it("should NOT update token metadata if the transaction is not signed with metadata key", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const operatorKey = env.operatorKey; + const metadataKey = PrivateKey.generateECDSA(); + const wrongMetadataKey = PrivateKey.generateECDSA(); + const supplyKey = PrivateKey.generateECDSA(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + + try { + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await ( + await tokenUpdateTx.sign(wrongMetadataKey) + ).execute(env.client) + ).getReceipt(env.client); + } catch (error) { + expect(error.status).to.be.eql(Status.InvalidSignature); + } + }); + + /** @summary Currently the transaction passing even when the metadata key is NOT set */ + it("should NOT update token metadata if the metadata key is NOT set", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const operatorKey = env.operatorKey; + const metadataKey = PrivateKey.generateECDSA(); + const supplyKey = PrivateKey.generateECDSA(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + + try { + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setMetadata(metadata); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await ( + await tokenUpdateTx.sign(metadataKey) + ).execute(env.client) + ).getReceipt(env.client); + } catch (error) { + expect(error.status).to.be.eql(Status.InvalidSignature); + } + }); + after(async function () { await env.close(); }); From 8e01632fcf3a9b1cd63b42a7268f6a9e2851b779 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Wed, 27 Mar 2024 10:20:32 +0200 Subject: [PATCH 11/30] update: add tests for fungible token Signed-off-by: svetoslav-nikol0v --- .../integration/TokenUpdateIntegrationTest.js | 256 +++++++++++++++++- 1 file changed, 250 insertions(+), 6 deletions(-) diff --git a/test/integration/TokenUpdateIntegrationTest.js b/test/integration/TokenUpdateIntegrationTest.js index ae65e4cff..464e93db7 100644 --- a/test/integration/TokenUpdateIntegrationTest.js +++ b/test/integration/TokenUpdateIntegrationTest.js @@ -444,7 +444,7 @@ describe("TokenUpdate", function () { } }); - it("should update token metadata", async function () { + it("should update the metadata of non-fungible token", async function () { this.timeout(120000); const operatorId = env.operatorId; @@ -492,7 +492,57 @@ describe("TokenUpdate", function () { expect(tokeInfo.metadata).to.eql(newMetadata); }); - it("should NOT update token metadata", async function () { + it("should update the metadata of fungible token", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const operatorKey = env.operatorKey; + const metadataKey = PrivateKey.generateECDSA(); + const supplyKey = PrivateKey.generateECDSA(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + let tokeInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokeInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + ).getReceipt(env.client); + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokeInfo.metadata).to.eql(newMetadata); + }); + + it("should NOT update the metadata of non-fungible token", async function () { this.timeout(120000); const operatorId = env.operatorId; @@ -538,7 +588,55 @@ describe("TokenUpdate", function () { expect(tokeInfo.metadata).to.eql(metadata); }); - it("should earse token metadata", async function () { + it("should NOT update the metadata of fungible token", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const operatorKey = env.operatorKey; + const metadataKey = PrivateKey.generateECDSA(); + const supplyKey = PrivateKey.generateECDSA(); + const metadata = new Uint8Array([1]); + let tokeInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokeInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + ).getReceipt(env.client); + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokeInfo.metadata).to.eql(metadata); + }); + + it("should earse the metadata of non-fungible token", async function () { this.timeout(120000); const operatorId = env.operatorId; @@ -586,8 +684,58 @@ describe("TokenUpdate", function () { expect(tokeInfo.metadata).to.eql(newMetadata); }); + it("should earse the metadata of fungible token", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const operatorKey = env.operatorKey; + const metadataKey = PrivateKey.generateECDSA(); + const supplyKey = PrivateKey.generateECDSA(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array(); + let tokeInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokeInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + ).getReceipt(env.client); + + tokeInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokeInfo.metadata).to.eql(newMetadata); + }); + /** @summary Currently the transaction passing even when the transaction is signed with wrong metadata key */ - it("should NOT update token metadata if the transaction is not signed with metadata key", async function () { + it("should NOT update the metadata of non-fungible token if the transaction is not signed with metadata key", async function () { this.timeout(120000); const operatorId = env.operatorId; @@ -632,8 +780,56 @@ describe("TokenUpdate", function () { } }); + /** @summary Currently the transaction passing even when the transaction is signed with wrong metadata key */ + it("should NOT update the metadata of fungible token if the transaction is not signed with metadata key", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const operatorKey = env.operatorKey; + const metadataKey = PrivateKey.generateECDSA(); + const wrongMetadataKey = PrivateKey.generateECDSA(); + const supplyKey = PrivateKey.generateECDSA(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + + try { + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await ( + await tokenUpdateTx.sign(wrongMetadataKey) + ).execute(env.client) + ).getReceipt(env.client); + } catch (error) { + expect(error.status).to.be.eql(Status.InvalidSignature); + } + }); + /** @summary Currently the transaction passing even when the metadata key is NOT set */ - it("should NOT update token metadata if the metadata key is NOT set", async function () { + it("should NOT update the metadata of non-fungible token if the metadata key is NOT set", async function () { this.timeout(120000); const operatorId = env.operatorId; @@ -651,7 +847,55 @@ describe("TokenUpdate", function () { .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) .setAdminKey(operatorKey) - .setMetadata(metadata); + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await ( + await tokenUpdateTx.sign(metadataKey) + ).execute(env.client) + ).getReceipt(env.client); + } catch (error) { + expect(error.status).to.be.eql(Status.InvalidSignature); + } + }); + + /** @summary Currently the transaction passing even when the metadata key is NOT set */ + it("should NOT update the metadata of fungible token if the metadata key is NOT set", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const operatorKey = env.operatorKey; + const metadataKey = PrivateKey.generateECDSA(); + const supplyKey = PrivateKey.generateECDSA(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + + try { + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) + .setAdminKey(operatorKey) + .setMetadata(metadata) + .setMetadataKey(metadataKey); const tokenCreateTxresponse = await tokenCreateTx.execute( env.client, From c86665c53d1e9ed9a9f8a68d452fe23a3dd08aa3 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Wed, 17 Apr 2024 16:23:22 +0300 Subject: [PATCH 12/30] update: integration tests Signed-off-by: svetoslav-nikol0v --- .../integration/TokenUpdateIntegrationTest.js | 414 ++++++++++++------ 1 file changed, 285 insertions(+), 129 deletions(-) diff --git a/test/integration/TokenUpdateIntegrationTest.js b/test/integration/TokenUpdateIntegrationTest.js index 464e93db7..c9c78e5c8 100644 --- a/test/integration/TokenUpdateIntegrationTest.js +++ b/test/integration/TokenUpdateIntegrationTest.js @@ -18,7 +18,7 @@ describe("TokenUpdate", function () { let env; before(async function () { - env = await IntegrationTestEnv.new(); + env = await IntegrationTestEnv.new({ balance: 10000 }); }); it("should be executable", async function () { @@ -298,21 +298,28 @@ describe("TokenUpdate", function () { it("should be exectuable when updating immutable token, but not setting any fields besides token ID", async function () { this.timeout(120000); + let status; const operatorId = env.operatorId; - const response = await new TokenCreateTransaction() - .setTokenName("ffff") - .setTokenSymbol("F") - .setTreasuryAccountId(operatorId) - .execute(env.client); + try { + const response = await new TokenCreateTransaction() + .setTokenName("ffff") + .setTokenSymbol("F") + .setTreasuryAccountId(operatorId) + .execute(env.client); - const token = (await response.getReceipt(env.client)).tokenId; + const token = (await response.getReceipt(env.client)).tokenId; - await ( - await new TokenUpdateTransaction() - .setTokenId(token) - .execute(env.client) - ).getReceipt(env.client); + await ( + await new TokenUpdateTransaction() + .setTokenId(token) + .execute(env.client) + ).getReceipt(env.client); + } catch (error) { + status = error.status; + } + + expect(status).to.eql(Status.TokenIsImmutable); }); it("should error when admin key does not sign transaction", async function () { @@ -433,7 +440,6 @@ describe("TokenUpdate", function () { ).execute(env.client) ).getReceipt(env.client); } catch (error) { - console.log(error); err = error .toString() .includes(Status.CurrentTreasuryStillOwnsNfts); @@ -444,16 +450,15 @@ describe("TokenUpdate", function () { } }); - it("should update the metadata of non-fungible token", async function () { + it("should update the metadata of non-fungible token after signing the transaction with metadata key", async function () { this.timeout(120000); const operatorId = env.operatorId; - const operatorKey = env.operatorKey; - const metadataKey = PrivateKey.generateECDSA(); - const supplyKey = PrivateKey.generateECDSA(); + const metadataKey = PrivateKey.generateED25519(); + const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); - let tokeInfo; + let tokenInfo; const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") @@ -461,7 +466,6 @@ describe("TokenUpdate", function () { .setSupplyKey(supplyKey) .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) .setMetadata(metadata) .setMetadataKey(metadataKey); @@ -471,10 +475,10 @@ describe("TokenUpdate", function () { ); const tokenId = tokenCreateTxReceipt.tokenId; - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(metadata); + expect(tokenInfo.metadata).to.eql(metadata); const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) @@ -485,33 +489,75 @@ describe("TokenUpdate", function () { await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) ).getReceipt(env.client); - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(newMetadata); + expect(tokenInfo.metadata).to.eql(newMetadata); }); - it("should update the metadata of fungible token", async function () { + it("should update the metadata of non-fungible token after signing the transaction with admin key", async function () { this.timeout(120000); + let tokenInfo; const operatorId = env.operatorId; - const operatorKey = env.operatorKey; - const metadataKey = PrivateKey.generateECDSA(); - const supplyKey = PrivateKey.generateECDSA(); + const adminKey = env.operatorKey; + const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); - let tokeInfo; const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") .setSupplyKey(supplyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(adminKey) + .setMetadata(metadata); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) + ).getReceipt(env.client); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + it("should update the metadata of fungible token after signing the transaction with metadata key", async function () { + this.timeout(120000); + + let tokenInfo; + const operatorId = env.operatorId; + const metadataKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") .setTokenType(TokenType.FungibleCommon) .setDecimals(3) .setInitialSupply(1000000) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) .setMetadata(metadata) .setMetadataKey(metadataKey); @@ -521,10 +567,10 @@ describe("TokenUpdate", function () { ); const tokenId = tokenCreateTxReceipt.tokenId; - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(metadata); + expect(tokenInfo.metadata).to.eql(metadata); const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) @@ -535,22 +581,67 @@ describe("TokenUpdate", function () { await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) ).getReceipt(env.client); - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + it("should update the metadata of fungible token after signing the transaction with admin key", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const adminKey = env.operatorKey; + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + let tokenInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) + .setAdminKey(adminKey) + .setMetadata(metadata); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) + ).getReceipt(env.client); + + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(newMetadata); + expect(tokenInfo.metadata).to.eql(newMetadata); }); - it("should NOT update the metadata of non-fungible token", async function () { + it("should NOT update the metadata of non-fungible token when the new metadata is NOT set", async function () { this.timeout(120000); + let tokenInfo; const operatorId = env.operatorId; - const operatorKey = env.operatorKey; - const metadataKey = PrivateKey.generateECDSA(); - const supplyKey = PrivateKey.generateECDSA(); + const adminKey = env.operatorKey; + const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); - let tokeInfo; const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") @@ -558,9 +649,8 @@ describe("TokenUpdate", function () { .setSupplyKey(supplyKey) .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) - .setMetadata(metadata) - .setMetadataKey(metadataKey); + .setAdminKey(adminKey) + .setMetadata(metadata); const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( @@ -568,47 +658,43 @@ describe("TokenUpdate", function () { ); const tokenId = tokenCreateTxReceipt.tokenId; - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(metadata); + expect(tokenInfo.metadata).to.eql(metadata); const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .freezeWith(env.client); await ( - await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) ).getReceipt(env.client); - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(metadata); + expect(tokenInfo.metadata).to.eql(metadata); }); - it("should NOT update the metadata of fungible token", async function () { + it("should NOT update the metadata of fungible token when the new metadata is NOT set", async function () { this.timeout(120000); const operatorId = env.operatorId; - const operatorKey = env.operatorKey; - const metadataKey = PrivateKey.generateECDSA(); - const supplyKey = PrivateKey.generateECDSA(); + const adminKey = env.operatorKey; const metadata = new Uint8Array([1]); - let tokeInfo; + let tokenInfo; const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") - .setSupplyKey(supplyKey) .setTokenType(TokenType.FungibleCommon) .setDecimals(3) .setInitialSupply(1000000) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) - .setMetadata(metadata) - .setMetadataKey(metadataKey); + .setAdminKey(adminKey) + .setMetadata(metadata); const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( @@ -616,36 +702,35 @@ describe("TokenUpdate", function () { ); const tokenId = tokenCreateTxReceipt.tokenId; - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(metadata); + expect(tokenInfo.metadata).to.eql(metadata); const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .freezeWith(env.client); await ( - await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) ).getReceipt(env.client); - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(metadata); + expect(tokenInfo.metadata).to.eql(metadata); }); - it("should earse the metadata of non-fungible token", async function () { + it("should earse the metadata of non-fungible token after signing the transaction with metadata key", async function () { this.timeout(120000); const operatorId = env.operatorId; - const operatorKey = env.operatorKey; - const metadataKey = PrivateKey.generateECDSA(); - const supplyKey = PrivateKey.generateECDSA(); + const metadataKey = PrivateKey.generateED25519(); + const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array(); - let tokeInfo; + let tokenInfo; const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") @@ -653,7 +738,6 @@ describe("TokenUpdate", function () { .setSupplyKey(supplyKey) .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) .setMetadata(metadata) .setMetadataKey(metadataKey); @@ -663,10 +747,10 @@ describe("TokenUpdate", function () { ); const tokenId = tokenCreateTxReceipt.tokenId; - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(metadata); + expect(tokenInfo.metadata).to.eql(metadata); const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) @@ -677,33 +761,75 @@ describe("TokenUpdate", function () { await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) ).getReceipt(env.client); - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(newMetadata); + expect(tokenInfo.metadata).to.eql(newMetadata); }); - it("should earse the metadata of fungible token", async function () { + it("should earse the metadata of non-fungible token after signing the transaction with admin key", async function () { this.timeout(120000); const operatorId = env.operatorId; - const operatorKey = env.operatorKey; - const metadataKey = PrivateKey.generateECDSA(); - const supplyKey = PrivateKey.generateECDSA(); + const adminKey = env.operatorKey; + const suppyKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array(); + let tokenInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(suppyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(adminKey) + .setMetadata(metadata); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) + ).getReceipt(env.client); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + it("should earse the metadata of fungible token after signing the transaction with metadata key", async function () { + this.timeout(120000); + + let tokenInfo; + const operatorId = env.operatorId; + const metadataKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array(); - let tokeInfo; const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") - .setSupplyKey(supplyKey) .setTokenType(TokenType.FungibleCommon) .setDecimals(3) .setInitialSupply(1000000) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) .setMetadata(metadata) .setMetadataKey(metadataKey); @@ -713,10 +839,10 @@ describe("TokenUpdate", function () { ); const tokenId = tokenCreateTxReceipt.tokenId; - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(metadata); + expect(tokenInfo.metadata).to.eql(metadata); const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) @@ -727,22 +853,68 @@ describe("TokenUpdate", function () { await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) ).getReceipt(env.client); - tokeInfo = await new TokenInfoQuery() + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + it("should earse the metadata of fungible token after signing the transaction with admin key", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const adminKey = env.operatorKey; + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array(); + let tokenInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) + .setMetadata(metadata) + .setAdminKey(adminKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) + ).getReceipt(env.client); + + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - expect(tokeInfo.metadata).to.eql(newMetadata); + expect(tokenInfo.metadata).to.eql(newMetadata); }); - /** @summary Currently the transaction passing even when the transaction is signed with wrong metadata key */ - it("should NOT update the metadata of non-fungible token if the transaction is not signed with metadata key", async function () { + it("should NOT update the metadata of non-fungible token when the transaction is not signed with metadata or admin key", async function () { this.timeout(120000); + let status; const operatorId = env.operatorId; - const operatorKey = env.operatorKey; - const metadataKey = PrivateKey.generateECDSA(); - const wrongMetadataKey = PrivateKey.generateECDSA(); - const supplyKey = PrivateKey.generateECDSA(); + const adminKey = PrivateKey.generateED25519(); + const metadataKey = PrivateKey.generateED25519(); + const wrongKey = PrivateKey.generateED25519(); + const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); @@ -753,7 +925,7 @@ describe("TokenUpdate", function () { .setSupplyKey(supplyKey) .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) + .setAdminKey(adminKey) .setMetadata(metadata) .setMetadataKey(metadataKey); @@ -771,24 +943,22 @@ describe("TokenUpdate", function () { .freezeWith(env.client); await ( - await ( - await tokenUpdateTx.sign(wrongMetadataKey) - ).execute(env.client) + await (await tokenUpdateTx.sign(wrongKey)).execute(env.client) ).getReceipt(env.client); } catch (error) { - expect(error.status).to.be.eql(Status.InvalidSignature); + status = error.status; } + expect(status).to.be.eql(Status.InvalidSignature); }); - /** @summary Currently the transaction passing even when the transaction is signed with wrong metadata key */ - it("should NOT update the metadata of fungible token if the transaction is not signed with metadata key", async function () { + it("should NOT update the metadata of fungible token when the transaction is not signed with metadata or admin key", async function () { this.timeout(120000); + let status; const operatorId = env.operatorId; - const operatorKey = env.operatorKey; - const metadataKey = PrivateKey.generateECDSA(); - const wrongMetadataKey = PrivateKey.generateECDSA(); - const supplyKey = PrivateKey.generateECDSA(); + const adminKey = PrivateKey.generateED25519(); + const metadataKey = PrivateKey.generateED25519(); + const wrongKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); @@ -796,12 +966,11 @@ describe("TokenUpdate", function () { const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") - .setSupplyKey(supplyKey) .setTokenType(TokenType.FungibleCommon) .setDecimals(3) .setInitialSupply(1000000) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) + .setAdminKey(adminKey) .setMetadata(metadata) .setMetadataKey(metadataKey); @@ -819,23 +988,20 @@ describe("TokenUpdate", function () { .freezeWith(env.client); await ( - await ( - await tokenUpdateTx.sign(wrongMetadataKey) - ).execute(env.client) + await (await tokenUpdateTx.sign(wrongKey)).execute(env.client) ).getReceipt(env.client); } catch (error) { - expect(error.status).to.be.eql(Status.InvalidSignature); + status = error.status; } + expect(status).to.be.eql(Status.InvalidSignature); }); - /** @summary Currently the transaction passing even when the metadata key is NOT set */ - it("should NOT update the metadata of non-fungible token if the metadata key is NOT set", async function () { + it("should NOT update the metadata of non-fungible token if the metadata or admin keys are NOT set", async function () { this.timeout(120000); + let status; const operatorId = env.operatorId; - const operatorKey = env.operatorKey; - const metadataKey = PrivateKey.generateECDSA(); - const supplyKey = PrivateKey.generateECDSA(); + const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); @@ -846,9 +1012,7 @@ describe("TokenUpdate", function () { .setSupplyKey(supplyKey) .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) - .setMetadata(metadata) - .setMetadataKey(metadataKey); + .setMetadata(metadata); const tokenCreateTxresponse = await tokenCreateTx.execute( env.client, @@ -864,23 +1028,19 @@ describe("TokenUpdate", function () { .freezeWith(env.client); await ( - await ( - await tokenUpdateTx.sign(metadataKey) - ).execute(env.client) + await tokenUpdateTx.execute(env.client) ).getReceipt(env.client); } catch (error) { - expect(error.status).to.be.eql(Status.InvalidSignature); + status = error.status; } + expect(status).to.be.eql(Status.TokenIsImmutable); }); - /** @summary Currently the transaction passing even when the metadata key is NOT set */ - it("should NOT update the metadata of fungible token if the metadata key is NOT set", async function () { + it("should NOT update the metadata of fungible token if the metadata or admin keys are NOT set", async function () { this.timeout(120000); + let status; const operatorId = env.operatorId; - const operatorKey = env.operatorKey; - const metadataKey = PrivateKey.generateECDSA(); - const supplyKey = PrivateKey.generateECDSA(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); @@ -888,14 +1048,11 @@ describe("TokenUpdate", function () { const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") - .setSupplyKey(supplyKey) .setTokenType(TokenType.FungibleCommon) .setDecimals(3) .setInitialSupply(1000000) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) - .setMetadata(metadata) - .setMetadataKey(metadataKey); + .setMetadata(metadata); const tokenCreateTxresponse = await tokenCreateTx.execute( env.client, @@ -911,13 +1068,12 @@ describe("TokenUpdate", function () { .freezeWith(env.client); await ( - await ( - await tokenUpdateTx.sign(metadataKey) - ).execute(env.client) + await tokenUpdateTx.execute(env.client) ).getReceipt(env.client); } catch (error) { - expect(error.status).to.be.eql(Status.InvalidSignature); + status = error.status; } + expect(status).to.be.eql(Status.TokenIsImmutable); }); after(async function () { From 0854410b051a39ff96fb624875ec7963d3b9299c Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Thu, 18 Apr 2024 10:23:11 +0300 Subject: [PATCH 13/30] update: unit tests Signed-off-by: svetoslav-nikol0v --- test/unit/TokenCreateTransaction.js | 10 ++++++++++ test/unit/TokenUpdateTransaction.js | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/test/unit/TokenCreateTransaction.js b/test/unit/TokenCreateTransaction.js index 90e8150ca..6e0aba90d 100644 --- a/test/unit/TokenCreateTransaction.js +++ b/test/unit/TokenCreateTransaction.js @@ -32,6 +32,10 @@ describe("TokenCreateTransaction", function () { const key7 = PrivateKey.fromStringDer( "302e020100300506032b657004220420542b4d4a318a1ae5f91071f34c8d900b1150e83d15fe71d22b8581e1203f99ad", ); + const key8 = PrivateKey.fromStringDer( + "302e020100300506032b6570042204205447805ce906170817e2bd4e26f4ea1fd5bbc38a2532c7f66b7d7a24f60ee9d5", + ); + const metadata = new Uint8Array([1, 2, 3, 4, 5]); const autoRenewAccountId = new AccountId(10); const treasuryAccountId = new AccountId(11); @@ -64,6 +68,8 @@ describe("TokenCreateTransaction", function () { .setWipeKey(key5) .setSupplyKey(key6) .setFeeScheduleKey(key7) + .setMetadata(metadata) + .setMetadataKey(key8) .setNodeAccountIds([new AccountId(4)]) .setTransactionMemo("random memo") .freeze(); @@ -109,6 +115,10 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: { ed25519: key7.publicKey.toBytesRaw(), }, + metadata: metadata, + metadataKey: { + ed25519: key8.publicKey.toBytesRaw(), + }, }, transactionFee: new Hbar(30).toTinybars(), memo: "random memo", diff --git a/test/unit/TokenUpdateTransaction.js b/test/unit/TokenUpdateTransaction.js index a8c83c5ed..303821ef6 100644 --- a/test/unit/TokenUpdateTransaction.js +++ b/test/unit/TokenUpdateTransaction.js @@ -30,6 +30,10 @@ describe("TokenUpdateTransaction", function () { const key7 = PrivateKey.fromStringDer( "302e020100300506032b657004220420542b4d4a318a1ae5f91071f34c8d900b1150e83d15fe71d22b8581e1203f99ad", ); + const key8 = PrivateKey.fromStringDer( + "302e020100300506032b6570042204205447805ce906170817e2bd4e26f4ea1fd5bbc38a2532c7f66b7d7a24f60ee9d5", + ); + const metadata = new Uint8Array([1, 2, 3, 4, 5]); const autoRenewAccountId = new AccountId(10); const treasuryAccountId = new AccountId(11); @@ -52,6 +56,8 @@ describe("TokenUpdateTransaction", function () { .setWipeKey(key5) .setSupplyKey(key6) .setFeeScheduleKey(key7) + .setMetadata(metadata) + .setMetadataKey(key8) .setNodeAccountIds([new AccountId(4)]) .setTokenId("0.0.5") .setTransactionMemo("random memo") @@ -96,6 +102,12 @@ describe("TokenUpdateTransaction", function () { feeScheduleKey: { ed25519: key7.publicKey.toBytesRaw(), }, + metadata: { + value: metadata, + }, + metadataKey: { + ed25519: key8.publicKey.toBytesRaw(), + }, }, transactionFee: Long.fromNumber(200000000), memo: "random memo", From 44888171583a2d3bac38353d2ab84dc745d50b50 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Thu, 18 Apr 2024 10:23:41 +0300 Subject: [PATCH 14/30] chore: proto version Signed-off-by: svetoslav-nikol0v --- package.json | 2 +- pnpm-lock.yaml | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 2e2148efe..9e190975b 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "@ethersproject/rlp": "^5.7.0", "@grpc/grpc-js": "1.8.2", "@hashgraph/cryptography": "1.4.8-beta.5", - "@hashgraph/proto": "link:packages/proto", + "@hashgraph/proto": "2.14.0-beta.5", "axios": "^1.6.4", "bignumber.js": "^9.1.1", "bn.js": "^5.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 27058ceb8..ae75d2b82 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,8 +24,8 @@ dependencies: specifier: 1.4.8-beta.5 version: 1.4.8-beta.5(expo@49.0.20) '@hashgraph/proto': - specifier: link:packages/proto - version: link:packages/proto + specifier: 2.14.0-beta.5 + version: 2.14.0-beta.5 axios: specifier: ^1.6.4 version: 1.6.5 @@ -2675,6 +2675,14 @@ packages: utf8: 3.0.0 dev: false + /@hashgraph/proto@2.14.0-beta.5: + resolution: {integrity: sha512-UrIbLdctpD//Ua99Z4PnknbR8220nc1Pzv0nkDJ1emZE9EAi7YOOry2Dw660azQHWfVw/HhqECPdiKrTIZ2b+Q==} + engines: {node: '>=10.0.0'} + dependencies: + long: 4.0.0 + protobufjs: 7.2.5 + dev: false + /@humanwhocodes/config-array@0.11.13: resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} From 8231dc5cf00183e227ab1f54bcaa87f1efd8400e Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Thu, 18 Apr 2024 14:14:39 +0300 Subject: [PATCH 15/30] update: examples for fungible token Signed-off-by: svetoslav-nikol0v --- ...-fungible-token-metadata-with-admin-key.js | 104 ++++++++++++++++++ ...gible-token-metadata-with-metadata-key.js} | 49 ++++++--- examples/update-nfts-metadata.js | 90 +++++++++++---- 3 files changed, 203 insertions(+), 40 deletions(-) create mode 100644 examples/update-fungible-token-metadata-with-admin-key.js rename examples/{update-token-metadata.js => update-fungible-token-metadata-with-metadata-key.js} (63%) diff --git a/examples/update-fungible-token-metadata-with-admin-key.js b/examples/update-fungible-token-metadata-with-admin-key.js new file mode 100644 index 000000000..341651451 --- /dev/null +++ b/examples/update-fungible-token-metadata-with-admin-key.js @@ -0,0 +1,104 @@ +import { + TokenCreateTransaction, + TokenInfoQuery, + TokenType, + PrivateKey, + Client, + AccountId, + TokenUpdateTransaction, +} from "@hashgraph/sdk"; +import dotenv from "dotenv"; + +dotenv.config(); + +/** + * @notice E2E-HIP-646 + * @url https://hips.hedera.com/hip/hip-646 + */ +async function main() { + if ( + !process.env.OPERATOR_KEY || + !process.env.OPERATOR_ID || + !process.env.HEDERA_NETWORK + ) { + throw new Error("Please set required keys in .env file."); + } + + const operatorId = AccountId.fromString(process.env.OPERATOR_ID); + const operatorKey = PrivateKey.fromStringDer(process.env.OPERATOR_KEY); + const network = process.env.HEDERA_NETWORK; + const client = Client.forName(network).setOperator(operatorId, operatorKey); + + // Generate a supply key + const adminKey = PrivateKey.fromStringDer(process.env.OPERATOR_KEY); + // Initial metadata + const metadata = new Uint8Array([1]); + // New metadata + const newMetadata = new Uint8Array([1, 2]); + + let tokenInfo; + + try { + // Create a non fungible token + let createTokenTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setMetadata(metadata) + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(10000) + .setTreasuryAccountId(operatorId) + .setAdminKey(adminKey) + .freezeWith(client); + + // Sign and execute create token transaction + const tokenCreateTxResponse = await ( + await createTokenTx.sign(operatorKey) + ).execute(client); + + // Get receipt for create token transaction + const tokenCreateTxReceipt = + await tokenCreateTxResponse.getReceipt(client); + console.log( + `Status of token create transction: ${tokenCreateTxReceipt.status.toString()}`, + ); + + // Get token id + const tokenId = tokenCreateTxReceipt.tokenId; + console.log(`Token id: ${tokenId.toString()}`); + + // Get token info + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(client); + console.log(`Token metadata:`, tokenInfo.metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(client); + + // Sign transactions with metadata key and execute it + const tokenUpdateTxResponse = await ( + await tokenUpdateTx.sign(adminKey) + ).execute(client); + + // Get receipt for token update transaction + const tokenUpdateTxReceipt = + await tokenUpdateTxResponse.getReceipt(client); + console.log( + `Status of token update transction: ${tokenUpdateTxReceipt.status.toString()}`, + ); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(client); + console.log(`Token updated metadata:`, tokenInfo.metadata); + } catch (error) { + console.log(error); + } + + client.close(); +} + +void main(); diff --git a/examples/update-token-metadata.js b/examples/update-fungible-token-metadata-with-metadata-key.js similarity index 63% rename from examples/update-token-metadata.js rename to examples/update-fungible-token-metadata-with-metadata-key.js index 7d2450053..18aadcd8d 100644 --- a/examples/update-token-metadata.js +++ b/examples/update-fungible-token-metadata-with-metadata-key.js @@ -1,11 +1,19 @@ -import { TokenCreateTransaction, TokenInfoQuery, TokenType, PrivateKey, Client, AccountId, TokenUpdateTransaction } from "@hashgraph/sdk"; +import { + TokenCreateTransaction, + TokenInfoQuery, + TokenType, + PrivateKey, + Client, + AccountId, + TokenUpdateTransaction, +} from "@hashgraph/sdk"; import dotenv from "dotenv"; dotenv.config(); /** - * @notice E2E-HIP-657 - * @url https://hips.hedera.com/hip/hip-657 + * @notice E2E-HIP-646 + * @url https://hips.hedera.com/hip/hip-646 */ async function main() { if ( @@ -22,7 +30,7 @@ async function main() { const client = Client.forName(network).setOperator(operatorId, operatorKey); // Generate a metadata key - const metadataKey = PrivateKey.generateECDSA(); + const metadataKey = PrivateKey.generateED25519(); // Initial metadata const metadata = new Uint8Array([1]); // New metadata @@ -36,20 +44,24 @@ async function main() { .setTokenName("Test") .setTokenSymbol("T") .setMetadata(metadata) - .setTokenType(TokenType.NonFungibleUnique) + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(10000) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) - .setTreasuryAccountId(operatorId) - .setSupplyKey(operatorKey) .setMetadataKey(metadataKey) .freezeWith(client); // Sign and execute create token transaction - const tokenCreateTxResponse = await (await createTokenTx.sign(operatorKey)).execute(client); + const tokenCreateTxResponse = await ( + await createTokenTx.sign(operatorKey) + ).execute(client); // Get receipt for create token transaction - const tokenCreateTxReceipt = await tokenCreateTxResponse.getReceipt(client); - console.log(`Status of token create transction: ${tokenCreateTxReceipt.status.toString()}`); + const tokenCreateTxReceipt = + await tokenCreateTxResponse.getReceipt(client); + console.log( + `Status of token create transction: ${tokenCreateTxReceipt.status.toString()}`, + ); // Get token id const tokenId = tokenCreateTxReceipt.tokenId; @@ -67,21 +79,26 @@ async function main() { .freezeWith(client); // Sign transactions with metadata key and execute it - const tokenUpdateTxResponse = await (await tokenUpdateTx.sign(metadataKey)).execute(client); + const tokenUpdateTxResponse = await ( + await tokenUpdateTx.sign(metadataKey) + ).execute(client); // Get receipt for token update transaction - const tokenUpdateTxReceipt = await tokenUpdateTxResponse.getReceipt(client); - console.log(`Status of token update transction: ${tokenUpdateTxReceipt.status.toString()}`); + const tokenUpdateTxReceipt = + await tokenUpdateTxResponse.getReceipt(client); + console.log( + `Status of token update transction: ${tokenUpdateTxReceipt.status.toString()}`, + ); tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(client); console.log(`Token updated metadata:`, tokenInfo.metadata); - } catch(error){ + } catch (error) { console.log(error); } - client.close() + client.close(); } void main(); diff --git a/examples/update-nfts-metadata.js b/examples/update-nfts-metadata.js index 4c47d3107..33ef782f6 100644 --- a/examples/update-nfts-metadata.js +++ b/examples/update-nfts-metadata.js @@ -1,4 +1,19 @@ -import { TokenCreateTransaction, TokenInfoQuery, TokenType, PrivateKey, Client, AccountId, TokenMintTransaction, TokenNftsUpdateTransaction, TokenNftInfoQuery, NftId, AccountCreateTransaction, Hbar, TransferTransaction, TokenAssociateTransaction } from "@hashgraph/sdk"; +import { + TokenCreateTransaction, + TokenInfoQuery, + TokenType, + PrivateKey, + Client, + AccountId, + TokenMintTransaction, + TokenNftsUpdateTransaction, + TokenNftInfoQuery, + NftId, + AccountCreateTransaction, + Hbar, + TransferTransaction, + TokenAssociateTransaction, +} from "@hashgraph/sdk"; import dotenv from "dotenv"; dotenv.config(); @@ -22,7 +37,9 @@ async function main() { const client = Client.forName(network).setOperator(operatorId, operatorKey); // Generate a metadata key - const metadataKey = PrivateKey.generateECDSA(); + const metadataKey = PrivateKey.generateED25519(); + // Generate a metadata key + const supplyKey = PrivateKey.generateED25519(); // Initial metadata const metadata = new Uint8Array([1]); // New metadata @@ -37,18 +54,21 @@ async function main() { .setTokenSymbol("T") .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) - .setAdminKey(operatorKey) - .setTreasuryAccountId(operatorId) - .setSupplyKey(operatorKey) + .setSupplyKey(supplyKey) .setMetadataKey(metadataKey) .freezeWith(client); // Sign and execute create token transaction - const tokenCreateTxResponse = await (await createTokenTx.sign(operatorKey)).execute(client); + const tokenCreateTxResponse = await ( + await createTokenTx.sign(operatorKey) + ).execute(client); // Get receipt for create token transaction - const tokenCreateTxReceipt = await tokenCreateTxResponse.getReceipt(client); - console.log(`Status of token create transction: ${tokenCreateTxReceipt.status.toString()}`); + const tokenCreateTxReceipt = + await tokenCreateTxResponse.getReceipt(client); + console.log( + `Status of token create transction: ${tokenCreateTxReceipt.status.toString()}`, + ); // Get token id const tokenId = tokenCreateTxReceipt.tokenId; @@ -66,9 +86,13 @@ async function main() { .setTokenId(tokenId) .freezeWith(client); - const tokenMintTxResponse = await(await tokenMintTx.sign(operatorKey)).execute(client); + const tokenMintTxResponse = await ( + await tokenMintTx.sign(supplyKey) + ).execute(client); const tokenMintTxReceipt = await tokenMintTxResponse.getReceipt(client); - console.log(`Status of token mint transction: ${tokenMintTxReceipt.status.toString()}`); + console.log( + `Status of token mint transction: ${tokenMintTxReceipt.status.toString()}`, + ); const nftSerial = tokenMintTxReceipt.serials[0]; @@ -86,28 +110,41 @@ async function main() { .setInitialBalance(new Hbar(100)) .freezeWith(client); - const accountCreateTxResponse = await(await accountCreateTx.sign(operatorKey)).execute(client); - const accountCreateTxReceipt = await accountCreateTxResponse.getReceipt(client); + const accountCreateTxResponse = await ( + await accountCreateTx.sign(operatorKey) + ).execute(client); + const accountCreateTxReceipt = + await accountCreateTxResponse.getReceipt(client); const newAccountId = accountCreateTxReceipt.accountId; console.log(`New account id: ${newAccountId.toString()}`); const tokenAssociateTx = new TokenAssociateTransaction() .setAccountId(newAccountId) .setTokenIds([tokenId]) - .freezeWith(client) + .freezeWith(client); - const tokenAssociateTxResponse = await(await tokenAssociateTx.sign(operatorKey)).execute(client); - const tokenAssociateTxReceipt = await tokenAssociateTxResponse.getReceipt(client); - console.log(`Status of token associate transaction: ${tokenAssociateTxReceipt.status.toString()}`); + const tokenAssociateTxResponse = await ( + await tokenAssociateTx.sign(operatorKey) + ).execute(client); + const tokenAssociateTxReceipt = + await tokenAssociateTxResponse.getReceipt(client); + console.log( + `Status of token associate transaction: ${tokenAssociateTxReceipt.status.toString()}`, + ); // Transfer nft to the new account const transferNftTx = new TransferTransaction() .addNftTransfer(tokenId, nftSerial, operatorId, newAccountId) .freezeWith(client); - const transferNftTxResponse = await(await transferNftTx.sign(operatorKey)).execute(client); - const transferNftTxReceipt = await transferNftTxResponse.getReceipt(client); - console.log(`Status of transfer NFT transaction: ${transferNftTxReceipt.status.toString()}`); + const transferNftTxResponse = await ( + await transferNftTx.sign(operatorKey) + ).execute(client); + const transferNftTxReceipt = + await transferNftTxResponse.getReceipt(client); + console.log( + `Status of transfer NFT transaction: ${transferNftTxReceipt.status.toString()}`, + ); // Update nfts metadata const tokenUpdateNftsTx = new TokenNftsUpdateTransaction() @@ -116,9 +153,14 @@ async function main() { .setMetadata(newMetadata) .freezeWith(client); - const tokenUpdateNftsTxResponse = await(await tokenUpdateNftsTx.sign(metadataKey)).execute(client); - const tokenUpdateNftsTxReceipt = await tokenUpdateNftsTxResponse.getReceipt(client); - console.log(`Status of token update nfts transction: ${tokenUpdateNftsTxReceipt.status.toString()}`); + const tokenUpdateNftsTxResponse = await ( + await tokenUpdateNftsTx.sign(metadataKey) + ).execute(client); + const tokenUpdateNftsTxReceipt = + await tokenUpdateNftsTxResponse.getReceipt(client); + console.log( + `Status of token update nfts transction: ${tokenUpdateNftsTxReceipt.status.toString()}`, + ); // Get token nfts info in order to show the metadata on the NFT created tokenNftsInfo = await new TokenNftInfoQuery() @@ -126,11 +168,11 @@ async function main() { .execute(client); nftInfo = tokenNftsInfo[0]; console.log(`Updated token NFT metadata:`, nftInfo.metadata); - } catch(error){ + } catch (error) { console.log(error); } - client.close() + client.close(); } void main(); From 38ef737ee16c9dafc902d260067f7a3fc2ff8362 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Thu, 18 Apr 2024 14:41:39 +0300 Subject: [PATCH 16/30] update: integration tests Signed-off-by: svetoslav-nikol0v --- .../integration/TokenUpdateIntegrationTest.js | 1101 +++++++++-------- 1 file changed, 553 insertions(+), 548 deletions(-) diff --git a/test/integration/TokenUpdateIntegrationTest.js b/test/integration/TokenUpdateIntegrationTest.js index c9c78e5c8..05f9e0972 100644 --- a/test/integration/TokenUpdateIntegrationTest.js +++ b/test/integration/TokenUpdateIntegrationTest.js @@ -14,7 +14,7 @@ import { } from "../../src/exports.js"; import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js"; -describe("TokenUpdate", function () { +describe.only("TokenUpdate", function () { let env; before(async function () { @@ -450,519 +450,107 @@ describe("TokenUpdate", function () { } }); - it("should update the metadata of non-fungible token after signing the transaction with metadata key", async function () { - this.timeout(120000); - - const operatorId = env.operatorId; - const metadataKey = PrivateKey.generateED25519(); - const supplyKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array([1, 2]); - let tokenInfo; - - const tokenCreateTx = new TokenCreateTransaction() - .setTokenName("Test") - .setTokenSymbol("T") - .setSupplyKey(supplyKey) - .setTokenType(TokenType.NonFungibleUnique) - .setTreasuryAccountId(operatorId) - .setMetadata(metadata) - .setMetadataKey(metadataKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); - const tokenId = tokenCreateTxReceipt.tokenId; - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - expect(tokenInfo.metadata).to.eql(metadata); - - const tokenUpdateTx = new TokenUpdateTransaction() - .setTokenId(tokenId) - .setMetadata(newMetadata) - .freezeWith(env.client); - - await ( - await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) - ).getReceipt(env.client); - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - - expect(tokenInfo.metadata).to.eql(newMetadata); - }); - - it("should update the metadata of non-fungible token after signing the transaction with admin key", async function () { - this.timeout(120000); - - let tokenInfo; - const operatorId = env.operatorId; - const adminKey = env.operatorKey; - const supplyKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array([1, 2]); - - const tokenCreateTx = new TokenCreateTransaction() - .setTokenName("Test") - .setTokenSymbol("T") - .setSupplyKey(supplyKey) - .setTokenType(TokenType.NonFungibleUnique) - .setTreasuryAccountId(operatorId) - .setAdminKey(adminKey) - .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); - const tokenId = tokenCreateTxReceipt.tokenId; - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - expect(tokenInfo.metadata).to.eql(metadata); - - const tokenUpdateTx = new TokenUpdateTransaction() - .setTokenId(tokenId) - .setMetadata(newMetadata) - .freezeWith(env.client); - - await ( - await (await tokenUpdateTx.sign(adminKey)).execute(env.client) - ).getReceipt(env.client); - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - - expect(tokenInfo.metadata).to.eql(newMetadata); - }); - - it("should update the metadata of fungible token after signing the transaction with metadata key", async function () { - this.timeout(120000); - - let tokenInfo; - const operatorId = env.operatorId; - const metadataKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array([1, 2]); - - const tokenCreateTx = new TokenCreateTransaction() - .setTokenName("Test") - .setTokenSymbol("T") - .setTokenType(TokenType.FungibleCommon) - .setDecimals(3) - .setInitialSupply(1000000) - .setTreasuryAccountId(operatorId) - .setMetadata(metadata) - .setMetadataKey(metadataKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); - const tokenId = tokenCreateTxReceipt.tokenId; - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - expect(tokenInfo.metadata).to.eql(metadata); - - const tokenUpdateTx = new TokenUpdateTransaction() - .setTokenId(tokenId) - .setMetadata(newMetadata) - .freezeWith(env.client); - - await ( - await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) - ).getReceipt(env.client); - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - - expect(tokenInfo.metadata).to.eql(newMetadata); - }); - - it("should update the metadata of fungible token after signing the transaction with admin key", async function () { - this.timeout(120000); - - const operatorId = env.operatorId; - const adminKey = env.operatorKey; - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array([1, 2]); - let tokenInfo; - - const tokenCreateTx = new TokenCreateTransaction() - .setTokenName("Test") - .setTokenSymbol("T") - .setTokenType(TokenType.FungibleCommon) - .setDecimals(3) - .setInitialSupply(1000000) - .setTreasuryAccountId(operatorId) - .setAdminKey(adminKey) - .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); - const tokenId = tokenCreateTxReceipt.tokenId; - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - expect(tokenInfo.metadata).to.eql(metadata); - - const tokenUpdateTx = new TokenUpdateTransaction() - .setTokenId(tokenId) - .setMetadata(newMetadata) - .freezeWith(env.client); - - await ( - await (await tokenUpdateTx.sign(adminKey)).execute(env.client) - ).getReceipt(env.client); - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - - expect(tokenInfo.metadata).to.eql(newMetadata); - }); - - it("should NOT update the metadata of non-fungible token when the new metadata is NOT set", async function () { - this.timeout(120000); - - let tokenInfo; - const operatorId = env.operatorId; - const adminKey = env.operatorKey; - const supplyKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array([1]); - - const tokenCreateTx = new TokenCreateTransaction() - .setTokenName("Test") - .setTokenSymbol("T") - .setSupplyKey(supplyKey) - .setTokenType(TokenType.NonFungibleUnique) - .setTreasuryAccountId(operatorId) - .setAdminKey(adminKey) - .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); - const tokenId = tokenCreateTxReceipt.tokenId; - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - expect(tokenInfo.metadata).to.eql(metadata); - - const tokenUpdateTx = new TokenUpdateTransaction() - .setTokenId(tokenId) - .freezeWith(env.client); - - await ( - await (await tokenUpdateTx.sign(adminKey)).execute(env.client) - ).getReceipt(env.client); - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - - expect(tokenInfo.metadata).to.eql(metadata); - }); - - it("should NOT update the metadata of fungible token when the new metadata is NOT set", async function () { - this.timeout(120000); - - const operatorId = env.operatorId; - const adminKey = env.operatorKey; - const metadata = new Uint8Array([1]); - let tokenInfo; - - const tokenCreateTx = new TokenCreateTransaction() - .setTokenName("Test") - .setTokenSymbol("T") - .setTokenType(TokenType.FungibleCommon) - .setDecimals(3) - .setInitialSupply(1000000) - .setTreasuryAccountId(operatorId) - .setAdminKey(adminKey) - .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); - const tokenId = tokenCreateTxReceipt.tokenId; - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - expect(tokenInfo.metadata).to.eql(metadata); - - const tokenUpdateTx = new TokenUpdateTransaction() - .setTokenId(tokenId) - .freezeWith(env.client); - - await ( - await (await tokenUpdateTx.sign(adminKey)).execute(env.client) - ).getReceipt(env.client); - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - - expect(tokenInfo.metadata).to.eql(metadata); - }); - - it("should earse the metadata of non-fungible token after signing the transaction with metadata key", async function () { - this.timeout(120000); - - const operatorId = env.operatorId; - const metadataKey = PrivateKey.generateED25519(); - const supplyKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array(); - let tokenInfo; - - const tokenCreateTx = new TokenCreateTransaction() - .setTokenName("Test") - .setTokenSymbol("T") - .setSupplyKey(supplyKey) - .setTokenType(TokenType.NonFungibleUnique) - .setTreasuryAccountId(operatorId) - .setMetadata(metadata) - .setMetadataKey(metadataKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); - const tokenId = tokenCreateTxReceipt.tokenId; - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - expect(tokenInfo.metadata).to.eql(metadata); - - const tokenUpdateTx = new TokenUpdateTransaction() - .setTokenId(tokenId) - .setMetadata(newMetadata) - .freezeWith(env.client); - - await ( - await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) - ).getReceipt(env.client); - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - - expect(tokenInfo.metadata).to.eql(newMetadata); - }); - - it("should earse the metadata of non-fungible token after signing the transaction with admin key", async function () { - this.timeout(120000); - - const operatorId = env.operatorId; - const adminKey = env.operatorKey; - const suppyKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array(); - let tokenInfo; - - const tokenCreateTx = new TokenCreateTransaction() - .setTokenName("Test") - .setTokenSymbol("T") - .setSupplyKey(suppyKey) - .setTokenType(TokenType.NonFungibleUnique) - .setTreasuryAccountId(operatorId) - .setAdminKey(adminKey) - .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); - const tokenId = tokenCreateTxReceipt.tokenId; - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - expect(tokenInfo.metadata).to.eql(metadata); - - const tokenUpdateTx = new TokenUpdateTransaction() - .setTokenId(tokenId) - .setMetadata(newMetadata) - .freezeWith(env.client); - - await ( - await (await tokenUpdateTx.sign(adminKey)).execute(env.client) - ).getReceipt(env.client); - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - - expect(tokenInfo.metadata).to.eql(newMetadata); - }); - - it("should earse the metadata of fungible token after signing the transaction with metadata key", async function () { - this.timeout(120000); - - let tokenInfo; - const operatorId = env.operatorId; - const metadataKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array(); - - const tokenCreateTx = new TokenCreateTransaction() - .setTokenName("Test") - .setTokenSymbol("T") - .setTokenType(TokenType.FungibleCommon) - .setDecimals(3) - .setInitialSupply(1000000) - .setTreasuryAccountId(operatorId) - .setMetadata(metadata) - .setMetadataKey(metadataKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); - const tokenId = tokenCreateTxReceipt.tokenId; - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - expect(tokenInfo.metadata).to.eql(metadata); - - const tokenUpdateTx = new TokenUpdateTransaction() - .setTokenId(tokenId) - .setMetadata(newMetadata) - .freezeWith(env.client); - - await ( - await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) - ).getReceipt(env.client); - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - - expect(tokenInfo.metadata).to.eql(newMetadata); - }); - - it("should earse the metadata of fungible token after signing the transaction with admin key", async function () { - this.timeout(120000); - - const operatorId = env.operatorId; - const adminKey = env.operatorKey; - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array(); - let tokenInfo; - - const tokenCreateTx = new TokenCreateTransaction() - .setTokenName("Test") - .setTokenSymbol("T") - .setTokenType(TokenType.FungibleCommon) - .setDecimals(3) - .setInitialSupply(1000000) - .setTreasuryAccountId(operatorId) - .setMetadata(metadata) - .setAdminKey(adminKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); - const tokenId = tokenCreateTxReceipt.tokenId; - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - expect(tokenInfo.metadata).to.eql(metadata); - - const tokenUpdateTx = new TokenUpdateTransaction() - .setTokenId(tokenId) - .setMetadata(newMetadata) - .freezeWith(env.client); - - await ( - await (await tokenUpdateTx.sign(adminKey)).execute(env.client) - ).getReceipt(env.client); - - tokenInfo = await new TokenInfoQuery() - .setTokenId(tokenId) - .execute(env.client); - - expect(tokenInfo.metadata).to.eql(newMetadata); - }); - - it("should NOT update the metadata of non-fungible token when the transaction is not signed with metadata or admin key", async function () { - this.timeout(120000); - - let status; - const operatorId = env.operatorId; - const adminKey = PrivateKey.generateED25519(); - const metadataKey = PrivateKey.generateED25519(); - const wrongKey = PrivateKey.generateED25519(); - const supplyKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array([1, 2]); - - try { + describe("[HIP-646] Fungible Token Metadata Field", function () { + it("should update the metadata of token after signing the transaction with metadata key", async function () { + this.timeout(120000); + + let tokenInfo; + const operatorId = env.operatorId; + const metadataKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") - .setSupplyKey(supplyKey) - .setTokenType(TokenType.NonFungibleUnique) + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) .setTreasuryAccountId(operatorId) - .setAdminKey(adminKey) .setMetadata(metadata) .setMetadataKey(metadataKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute( + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + ).getReceipt(env.client); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + it("should update the metadata of token after signing the transaction with admin key", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const adminKey = env.operatorKey; + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + let tokenInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) + .setAdminKey(adminKey) + .setMetadata(metadata); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( - await (await tokenUpdateTx.sign(wrongKey)).execute(env.client) + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) ).getReceipt(env.client); - } catch (error) { - status = error.status; - } - expect(status).to.be.eql(Status.InvalidSignature); - }); - - it("should NOT update the metadata of fungible token when the transaction is not signed with metadata or admin key", async function () { - this.timeout(120000); - - let status; - const operatorId = env.operatorId; - const adminKey = PrivateKey.generateED25519(); - const metadataKey = PrivateKey.generateED25519(); - const wrongKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array([1, 2]); - - try { + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + it("should NOT update the metadata of token when the new metadata is NOT set", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const adminKey = env.operatorKey; + const metadata = new Uint8Array([1]); + let tokenInfo; + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") @@ -971,109 +559,526 @@ describe("TokenUpdate", function () { .setInitialSupply(1000000) .setTreasuryAccountId(operatorId) .setAdminKey(adminKey) + .setMetadata(metadata); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) + ).getReceipt(env.client); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(metadata); + }); + + it("should earse the metadata of token after signing the transaction with metadata key", async function () { + this.timeout(120000); + + let tokenInfo; + const operatorId = env.operatorId; + const metadataKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array(); + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) .setMetadata(metadata) .setMetadataKey(metadataKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute( + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + ).getReceipt(env.client); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + it("should earse the metadata of token after signing the transaction with admin key", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const adminKey = env.operatorKey; + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array(); + let tokenInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) + .setMetadata(metadata) + .setAdminKey(adminKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( - await (await tokenUpdateTx.sign(wrongKey)).execute(env.client) + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) ).getReceipt(env.client); - } catch (error) { - status = error.status; - } - expect(status).to.be.eql(Status.InvalidSignature); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + + it("should NOT update the metadata of token when the transaction is not signed with metadata or admin key", async function () { + this.timeout(120000); + + let status; + const operatorId = env.operatorId; + const adminKey = PrivateKey.generateED25519(); + const metadataKey = PrivateKey.generateED25519(); + const wrongKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + + try { + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) + .setAdminKey(adminKey) + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(wrongKey)).execute(env.client) + ).getReceipt(env.client); + } catch (error) { + status = error.status; + } + expect(status).to.be.eql(Status.InvalidSignature); + }); + + it("should NOT update the metadata of token if the metadata or admin keys are NOT set", async function () { + this.timeout(120000); + + let status; + const operatorId = env.operatorId; + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + + try { + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setTokenType(TokenType.FungibleCommon) + .setDecimals(3) + .setInitialSupply(1000000) + .setTreasuryAccountId(operatorId) + .setMetadata(metadata); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await tokenUpdateTx.execute(env.client) + ).getReceipt(env.client); + } catch (error) { + status = error.status; + } + expect(status).to.be.eql(Status.TokenIsImmutable); + }); }); - it("should NOT update the metadata of non-fungible token if the metadata or admin keys are NOT set", async function () { - this.timeout(120000); - - let status; - const operatorId = env.operatorId; - const supplyKey = PrivateKey.generateED25519(); - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array([1, 2]); - - try { + describe("[HIP-765] Non Fungible Token Metadata Field", function () { + it("should update the metadata of token after signing the transaction with metadata key", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const metadataKey = PrivateKey.generateED25519(); + const supplyKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + let tokenInfo; + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") .setSupplyKey(supplyKey) .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) - .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute( + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + ).getReceipt(env.client); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + it("should update the metadata of token after signing the transaction with admin key", async function () { + this.timeout(120000); + + let tokenInfo; + const operatorId = env.operatorId; + const adminKey = env.operatorKey; + const supplyKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(adminKey) + .setMetadata(metadata); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( - await tokenUpdateTx.execute(env.client) + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) ).getReceipt(env.client); - } catch (error) { - status = error.status; - } - expect(status).to.be.eql(Status.TokenIsImmutable); - }); - - it("should NOT update the metadata of fungible token if the metadata or admin keys are NOT set", async function () { - this.timeout(120000); - - let status; - const operatorId = env.operatorId; - const metadata = new Uint8Array([1]); - const newMetadata = new Uint8Array([1, 2]); - - try { + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + it("should NOT update the metadata of token when the new metadata is NOT set", async function () { + this.timeout(120000); + + let tokenInfo; + const operatorId = env.operatorId; + const adminKey = env.operatorKey; + const supplyKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") - .setTokenType(TokenType.FungibleCommon) - .setDecimals(3) - .setInitialSupply(1000000) + .setSupplyKey(supplyKey) + .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) + .setAdminKey(adminKey) .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute( + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) + ).getReceipt(env.client); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(metadata); + }); + + it("should earse the metadata of token after signing the transaction with metadata key", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const metadataKey = PrivateKey.generateED25519(); + const supplyKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array(); + let tokenInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( - await tokenUpdateTx.execute(env.client) + await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) ).getReceipt(env.client); - } catch (error) { - status = error.status; - } - expect(status).to.be.eql(Status.TokenIsImmutable); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + it("should earse the metadata of token after signing the transaction with admin key", async function () { + this.timeout(120000); + + const operatorId = env.operatorId; + const adminKey = env.operatorKey; + const suppyKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array(); + let tokenInfo; + + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(suppyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(adminKey) + .setMetadata(metadata); + + const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + expect(tokenInfo.metadata).to.eql(metadata); + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(adminKey)).execute(env.client) + ).getReceipt(env.client); + + tokenInfo = await new TokenInfoQuery() + .setTokenId(tokenId) + .execute(env.client); + + expect(tokenInfo.metadata).to.eql(newMetadata); + }); + + it("should NOT update the metadata of token when the transaction is not signed with metadata or admin key", async function () { + this.timeout(120000); + + let status; + const operatorId = env.operatorId; + const adminKey = PrivateKey.generateED25519(); + const metadataKey = PrivateKey.generateED25519(); + const wrongKey = PrivateKey.generateED25519(); + const supplyKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + + try { + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setAdminKey(adminKey) + .setMetadata(metadata) + .setMetadataKey(metadataKey); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await (await tokenUpdateTx.sign(wrongKey)).execute(env.client) + ).getReceipt(env.client); + } catch (error) { + status = error.status; + } + expect(status).to.be.eql(Status.InvalidSignature); + }); + + it("should NOT update the metadata of token if the metadata or admin keys are NOT set", async function () { + this.timeout(120000); + + let status; + const operatorId = env.operatorId; + const supplyKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); + const newMetadata = new Uint8Array([1, 2]); + + try { + const tokenCreateTx = new TokenCreateTransaction() + .setTokenName("Test") + .setTokenSymbol("T") + .setSupplyKey(supplyKey) + .setTokenType(TokenType.NonFungibleUnique) + .setTreasuryAccountId(operatorId) + .setMetadata(metadata); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); + const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( + env.client, + ); + const tokenId = tokenCreateTxReceipt.tokenId; + + const tokenUpdateTx = new TokenUpdateTransaction() + .setTokenId(tokenId) + .setMetadata(newMetadata) + .freezeWith(env.client); + + await ( + await tokenUpdateTx.execute(env.client) + ).getReceipt(env.client); + } catch (error) { + status = error.status; + } + expect(status).to.be.eql(Status.TokenIsImmutable); + }); }); after(async function () { From 9f128cdbb67748864ee3d0cc2b71577b4e059d9b Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Thu, 18 Apr 2024 14:53:41 +0300 Subject: [PATCH 17/30] chore: network tag Signed-off-by: svetoslav-nikol0v --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ee93701c2..9dbcaf7fd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -102,7 +102,7 @@ jobs: id: start-local-node if: ${{ steps.build-sdk.conclusion == 'success' && !cancelled() && always() }} run: | - npx @hashgraph/hedera-local start -d --network-tag=0.48.0 --balance=100000 + npx @hashgraph/hedera-local start -d --network local --balance=100000 # Wait for the network to fully start sleep 30 From f6cc669de565b03f92b015b677b730dc6d762b7b Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Thu, 18 Apr 2024 16:51:50 +0300 Subject: [PATCH 18/30] chore: formatting Signed-off-by: svetoslav-nikol0v --- .../integration/TokenUpdateIntegrationTest.js | 293 ++++++++++-------- 1 file changed, 160 insertions(+), 133 deletions(-) diff --git a/test/integration/TokenUpdateIntegrationTest.js b/test/integration/TokenUpdateIntegrationTest.js index 05f9e0972..65ee48431 100644 --- a/test/integration/TokenUpdateIntegrationTest.js +++ b/test/integration/TokenUpdateIntegrationTest.js @@ -14,7 +14,7 @@ import { } from "../../src/exports.js"; import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js"; -describe.only("TokenUpdate", function () { +describe("TokenUpdate", function () { let env; before(async function () { @@ -453,13 +453,13 @@ describe.only("TokenUpdate", function () { describe("[HIP-646] Fungible Token Metadata Field", function () { it("should update the metadata of token after signing the transaction with metadata key", async function () { this.timeout(120000); - + let tokenInfo; const operatorId = env.operatorId; const metadataKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); - + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") @@ -469,43 +469,47 @@ describe.only("TokenUpdate", function () { .setTreasuryAccountId(operatorId) .setMetadata(metadata) .setMetadataKey(metadataKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); expect(tokenInfo.metadata).to.eql(metadata); - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( - await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + await ( + await tokenUpdateTx.sign(metadataKey) + ).execute(env.client) ).getReceipt(env.client); - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - + expect(tokenInfo.metadata).to.eql(newMetadata); }); - + it("should update the metadata of token after signing the transaction with admin key", async function () { this.timeout(120000); - + const operatorId = env.operatorId; const adminKey = env.operatorKey; const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); let tokenInfo; - + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") @@ -515,42 +519,44 @@ describe.only("TokenUpdate", function () { .setTreasuryAccountId(operatorId) .setAdminKey(adminKey) .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); expect(tokenInfo.metadata).to.eql(metadata); - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( await (await tokenUpdateTx.sign(adminKey)).execute(env.client) ).getReceipt(env.client); - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - + expect(tokenInfo.metadata).to.eql(newMetadata); }); it("should NOT update the metadata of token when the new metadata is NOT set", async function () { this.timeout(120000); - + const operatorId = env.operatorId; const adminKey = env.operatorKey; const metadata = new Uint8Array([1]); let tokenInfo; - + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") @@ -560,42 +566,44 @@ describe.only("TokenUpdate", function () { .setTreasuryAccountId(operatorId) .setAdminKey(adminKey) .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); expect(tokenInfo.metadata).to.eql(metadata); - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .freezeWith(env.client); - + await ( await (await tokenUpdateTx.sign(adminKey)).execute(env.client) ).getReceipt(env.client); - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - + expect(tokenInfo.metadata).to.eql(metadata); }); it("should earse the metadata of token after signing the transaction with metadata key", async function () { this.timeout(120000); - + let tokenInfo; const operatorId = env.operatorId; const metadataKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array(); - + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") @@ -605,43 +613,47 @@ describe.only("TokenUpdate", function () { .setTreasuryAccountId(operatorId) .setMetadata(metadata) .setMetadataKey(metadataKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); expect(tokenInfo.metadata).to.eql(metadata); - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( - await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + await ( + await tokenUpdateTx.sign(metadataKey) + ).execute(env.client) ).getReceipt(env.client); - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - + expect(tokenInfo.metadata).to.eql(newMetadata); }); - + it("should earse the metadata of token after signing the transaction with admin key", async function () { this.timeout(120000); - + const operatorId = env.operatorId; const adminKey = env.operatorKey; const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array(); let tokenInfo; - + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") @@ -651,38 +663,39 @@ describe.only("TokenUpdate", function () { .setTreasuryAccountId(operatorId) .setMetadata(metadata) .setAdminKey(adminKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); expect(tokenInfo.metadata).to.eql(metadata); - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( await (await tokenUpdateTx.sign(adminKey)).execute(env.client) ).getReceipt(env.client); - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - + expect(tokenInfo.metadata).to.eql(newMetadata); }); - it("should NOT update the metadata of token when the transaction is not signed with metadata or admin key", async function () { this.timeout(120000); - + let status; const operatorId = env.operatorId; const adminKey = PrivateKey.generateED25519(); @@ -690,7 +703,7 @@ describe.only("TokenUpdate", function () { const wrongKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); - + try { const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") @@ -702,22 +715,23 @@ describe.only("TokenUpdate", function () { .setAdminKey(adminKey) .setMetadata(metadata) .setMetadataKey(metadataKey); - + const tokenCreateTxresponse = await tokenCreateTx.execute( env.client, ); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); + const tokenCreateTxReceipt = + await tokenCreateTxresponse.getReceipt(env.client); const tokenId = tokenCreateTxReceipt.tokenId; - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( - await (await tokenUpdateTx.sign(wrongKey)).execute(env.client) + await ( + await tokenUpdateTx.sign(wrongKey) + ).execute(env.client) ).getReceipt(env.client); } catch (error) { status = error.status; @@ -727,12 +741,12 @@ describe.only("TokenUpdate", function () { it("should NOT update the metadata of token if the metadata or admin keys are NOT set", async function () { this.timeout(120000); - + let status; const operatorId = env.operatorId; const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); - + try { const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") @@ -742,20 +756,19 @@ describe.only("TokenUpdate", function () { .setInitialSupply(1000000) .setTreasuryAccountId(operatorId) .setMetadata(metadata); - + const tokenCreateTxresponse = await tokenCreateTx.execute( env.client, ); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); + const tokenCreateTxReceipt = + await tokenCreateTxresponse.getReceipt(env.client); const tokenId = tokenCreateTxReceipt.tokenId; - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( await tokenUpdateTx.execute(env.client) ).getReceipt(env.client); @@ -769,14 +782,14 @@ describe.only("TokenUpdate", function () { describe("[HIP-765] Non Fungible Token Metadata Field", function () { it("should update the metadata of token after signing the transaction with metadata key", async function () { this.timeout(120000); - + const operatorId = env.operatorId; const metadataKey = PrivateKey.generateED25519(); const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); let tokenInfo; - + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") @@ -785,44 +798,48 @@ describe.only("TokenUpdate", function () { .setTreasuryAccountId(operatorId) .setMetadata(metadata) .setMetadataKey(metadataKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); expect(tokenInfo.metadata).to.eql(metadata); - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( - await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + await ( + await tokenUpdateTx.sign(metadataKey) + ).execute(env.client) ).getReceipt(env.client); - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - + expect(tokenInfo.metadata).to.eql(newMetadata); }); it("should update the metadata of token after signing the transaction with admin key", async function () { this.timeout(120000); - + let tokenInfo; const operatorId = env.operatorId; const adminKey = env.operatorKey; const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); - + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") @@ -831,43 +848,45 @@ describe.only("TokenUpdate", function () { .setTreasuryAccountId(operatorId) .setAdminKey(adminKey) .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); expect(tokenInfo.metadata).to.eql(metadata); - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( await (await tokenUpdateTx.sign(adminKey)).execute(env.client) ).getReceipt(env.client); - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - + expect(tokenInfo.metadata).to.eql(newMetadata); }); it("should NOT update the metadata of token when the new metadata is NOT set", async function () { this.timeout(120000); - + let tokenInfo; const operatorId = env.operatorId; const adminKey = env.operatorKey; const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); - + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") @@ -876,43 +895,45 @@ describe.only("TokenUpdate", function () { .setTreasuryAccountId(operatorId) .setAdminKey(adminKey) .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); expect(tokenInfo.metadata).to.eql(metadata); - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .freezeWith(env.client); - + await ( await (await tokenUpdateTx.sign(adminKey)).execute(env.client) ).getReceipt(env.client); - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - + expect(tokenInfo.metadata).to.eql(metadata); }); it("should earse the metadata of token after signing the transaction with metadata key", async function () { this.timeout(120000); - + const operatorId = env.operatorId; const metadataKey = PrivateKey.generateED25519(); const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array(); let tokenInfo; - + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") @@ -921,44 +942,48 @@ describe.only("TokenUpdate", function () { .setTreasuryAccountId(operatorId) .setMetadata(metadata) .setMetadataKey(metadataKey); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); expect(tokenInfo.metadata).to.eql(metadata); - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( - await (await tokenUpdateTx.sign(metadataKey)).execute(env.client) + await ( + await tokenUpdateTx.sign(metadataKey) + ).execute(env.client) ).getReceipt(env.client); - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - + expect(tokenInfo.metadata).to.eql(newMetadata); }); - + it("should earse the metadata of token after signing the transaction with admin key", async function () { this.timeout(120000); - + const operatorId = env.operatorId; const adminKey = env.operatorKey; const suppyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array(); let tokenInfo; - + const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") .setTokenSymbol("T") @@ -967,37 +992,39 @@ describe.only("TokenUpdate", function () { .setTreasuryAccountId(operatorId) .setAdminKey(adminKey) .setMetadata(metadata); - - const tokenCreateTxresponse = await tokenCreateTx.execute(env.client); + + const tokenCreateTxresponse = await tokenCreateTx.execute( + env.client, + ); const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( env.client, ); const tokenId = tokenCreateTxReceipt.tokenId; - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); expect(tokenInfo.metadata).to.eql(metadata); - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( await (await tokenUpdateTx.sign(adminKey)).execute(env.client) ).getReceipt(env.client); - + tokenInfo = await new TokenInfoQuery() .setTokenId(tokenId) .execute(env.client); - + expect(tokenInfo.metadata).to.eql(newMetadata); }); it("should NOT update the metadata of token when the transaction is not signed with metadata or admin key", async function () { this.timeout(120000); - + let status; const operatorId = env.operatorId; const adminKey = PrivateKey.generateED25519(); @@ -1006,7 +1033,7 @@ describe.only("TokenUpdate", function () { const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); - + try { const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") @@ -1017,22 +1044,23 @@ describe.only("TokenUpdate", function () { .setAdminKey(adminKey) .setMetadata(metadata) .setMetadataKey(metadataKey); - + const tokenCreateTxresponse = await tokenCreateTx.execute( env.client, ); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); + const tokenCreateTxReceipt = + await tokenCreateTxresponse.getReceipt(env.client); const tokenId = tokenCreateTxReceipt.tokenId; - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( - await (await tokenUpdateTx.sign(wrongKey)).execute(env.client) + await ( + await tokenUpdateTx.sign(wrongKey) + ).execute(env.client) ).getReceipt(env.client); } catch (error) { status = error.status; @@ -1042,13 +1070,13 @@ describe.only("TokenUpdate", function () { it("should NOT update the metadata of token if the metadata or admin keys are NOT set", async function () { this.timeout(120000); - + let status; const operatorId = env.operatorId; const supplyKey = PrivateKey.generateED25519(); const metadata = new Uint8Array([1]); const newMetadata = new Uint8Array([1, 2]); - + try { const tokenCreateTx = new TokenCreateTransaction() .setTokenName("Test") @@ -1057,20 +1085,19 @@ describe.only("TokenUpdate", function () { .setTokenType(TokenType.NonFungibleUnique) .setTreasuryAccountId(operatorId) .setMetadata(metadata); - + const tokenCreateTxresponse = await tokenCreateTx.execute( env.client, ); - const tokenCreateTxReceipt = await tokenCreateTxresponse.getReceipt( - env.client, - ); + const tokenCreateTxReceipt = + await tokenCreateTxresponse.getReceipt(env.client); const tokenId = tokenCreateTxReceipt.tokenId; - + const tokenUpdateTx = new TokenUpdateTransaction() .setTokenId(tokenId) .setMetadata(newMetadata) .freezeWith(env.client); - + await ( await tokenUpdateTx.execute(env.client) ).getReceipt(env.client); From 5040397eae506dff0b5ca72e890c99c0e979f704 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Fri, 19 Apr 2024 10:22:02 +0300 Subject: [PATCH 19/30] update: examples Signed-off-by: svetoslav-nikol0v --- examples/update-fungible-token-metadata-with-admin-key.js | 5 +++-- examples/update-fungible-token-metadata-with-metadata-key.js | 3 ++- ...data.js => update-nfts-metadata-of-non-fungible-token.js} | 0 3 files changed, 5 insertions(+), 3 deletions(-) rename examples/{update-nfts-metadata.js => update-nfts-metadata-of-non-fungible-token.js} (100%) diff --git a/examples/update-fungible-token-metadata-with-admin-key.js b/examples/update-fungible-token-metadata-with-admin-key.js index 341651451..9d6f1ec3c 100644 --- a/examples/update-fungible-token-metadata-with-admin-key.js +++ b/examples/update-fungible-token-metadata-with-admin-key.js @@ -14,6 +14,7 @@ dotenv.config(); /** * @notice E2E-HIP-646 * @url https://hips.hedera.com/hip/hip-646 + * @description Update fungible token metadata with admin key */ async function main() { if ( @@ -44,7 +45,7 @@ async function main() { .setTokenName("Test") .setTokenSymbol("T") .setMetadata(metadata) - .setTokenType(TokenType.FungibleCommon) + .setTokenType(TokenType.FungibleCommon) // Can be TokenType.NonFungibleUnique as well [HIP-765] .setDecimals(3) .setInitialSupply(10000) .setTreasuryAccountId(operatorId) @@ -78,7 +79,7 @@ async function main() { .setMetadata(newMetadata) .freezeWith(client); - // Sign transactions with metadata key and execute it + // Sign transactions with admin key and execute it const tokenUpdateTxResponse = await ( await tokenUpdateTx.sign(adminKey) ).execute(client); diff --git a/examples/update-fungible-token-metadata-with-metadata-key.js b/examples/update-fungible-token-metadata-with-metadata-key.js index 18aadcd8d..843cadc67 100644 --- a/examples/update-fungible-token-metadata-with-metadata-key.js +++ b/examples/update-fungible-token-metadata-with-metadata-key.js @@ -14,6 +14,7 @@ dotenv.config(); /** * @notice E2E-HIP-646 * @url https://hips.hedera.com/hip/hip-646 + * @description Update fungible token metadata with metadata key */ async function main() { if ( @@ -44,7 +45,7 @@ async function main() { .setTokenName("Test") .setTokenSymbol("T") .setMetadata(metadata) - .setTokenType(TokenType.FungibleCommon) + .setTokenType(TokenType.FungibleCommon) // Can be TokenType.NonFungibleUnique as well [HIP-765] .setDecimals(3) .setInitialSupply(10000) .setTreasuryAccountId(operatorId) diff --git a/examples/update-nfts-metadata.js b/examples/update-nfts-metadata-of-non-fungible-token.js similarity index 100% rename from examples/update-nfts-metadata.js rename to examples/update-nfts-metadata-of-non-fungible-token.js From 70b4ea0765b483345ce8aa96002697ce8def2025 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Fri, 19 Apr 2024 10:34:41 +0300 Subject: [PATCH 20/30] update: integration tests Signed-off-by: svetoslav-nikol0v --- test/integration/TokenUpdateIntegrationTest.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/test/integration/TokenUpdateIntegrationTest.js b/test/integration/TokenUpdateIntegrationTest.js index 65ee48431..25e309788 100644 --- a/test/integration/TokenUpdateIntegrationTest.js +++ b/test/integration/TokenUpdateIntegrationTest.js @@ -31,6 +31,9 @@ describe("TokenUpdate", function () { const key3 = PrivateKey.generateED25519(); const key4 = PrivateKey.generateED25519(); const key5 = PrivateKey.generateED25519(); + const metadataKey = PrivateKey.generateED25519(); + const newMetadataKey = PrivateKey.generateED25519(); + const metadata = new Uint8Array([1]); const response = await new TokenCreateTransaction() .setTokenName("ffff") @@ -45,6 +48,8 @@ describe("TokenUpdate", function () { .setSupplyKey(key4) .setFreezeDefault(false) .setPauseKey(key5) + .setMetadata(metadata) + .setMetadataKey(metadataKey) .execute(env.client); const token = (await response.getReceipt(env.client)).tokenId; @@ -67,6 +72,8 @@ describe("TokenUpdate", function () { expect(info.wipeKey.toString()).to.eql(key3.publicKey.toString()); expect(info.supplyKey.toString()).to.eql(key4.publicKey.toString()); expect(info.pauseKey.toString()).to.eql(key5.publicKey.toString()); + expect(info.metadataKey.toString()).to.eql(metadataKey.publicKey.toString()); + expect(info.metadata).to.eql(metadata); expect(info.defaultFreezeStatus).to.be.false; expect(info.defaultKycStatus).to.be.false; expect(info.isDeleted).to.be.false; @@ -79,6 +86,7 @@ describe("TokenUpdate", function () { .setTokenId(token) .setTokenName("aaaa") .setTokenSymbol("A") + .setMetadataKey(newMetadataKey) .execute(env.client) ).getReceipt(env.client); @@ -97,6 +105,8 @@ describe("TokenUpdate", function () { expect(info.freezeKey.toString()).to.eql(key2.publicKey.toString()); expect(info.wipeKey.toString()).to.eql(key3.publicKey.toString()); expect(info.supplyKey.toString()).to.eql(key4.publicKey.toString()); + expect(info.metadataKey.toString()).to.eql(newMetadataKey.publicKey.toString()); + expect(info.metadata).to.eql(metadata); expect(info.defaultFreezeStatus).to.be.false; expect(info.defaultKycStatus).to.be.false; expect(info.isDeleted).to.be.false; @@ -258,7 +268,7 @@ describe("TokenUpdate", function () { const token = (await response.getReceipt(env.client)).tokenId; - let err = false; + let status; try { await ( @@ -269,12 +279,10 @@ describe("TokenUpdate", function () { .execute(env.client) ).getReceipt(env.client); } catch (error) { - err = error.toString().includes(Status.TokenIsImmutable); + status = error.status; } - if (!err) { - throw new Error("token update did not error"); - } + expect(status).to.be.eql(Status.TokenIsImmutable); }); it("should error when token ID is not set", async function () { From 183b2b032cc57a4d95ed4ccfbe616824edbaa887 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Fri, 19 Apr 2024 11:18:08 +0300 Subject: [PATCH 21/30] chore: network tag Signed-off-by: svetoslav-nikol0v --- .github/workflows/build.yml | 2 +- test/integration/TokenUpdateIntegrationTest.js | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9dbcaf7fd..80880a35a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -102,7 +102,7 @@ jobs: id: start-local-node if: ${{ steps.build-sdk.conclusion == 'success' && !cancelled() && always() }} run: | - npx @hashgraph/hedera-local start -d --network local --balance=100000 + npx @hashgraph/hedera-local start -d —network-tag=0.49.0-alpha.4 --balance=100000 # Wait for the network to fully start sleep 30 diff --git a/test/integration/TokenUpdateIntegrationTest.js b/test/integration/TokenUpdateIntegrationTest.js index 25e309788..cfc5ce553 100644 --- a/test/integration/TokenUpdateIntegrationTest.js +++ b/test/integration/TokenUpdateIntegrationTest.js @@ -72,7 +72,9 @@ describe("TokenUpdate", function () { expect(info.wipeKey.toString()).to.eql(key3.publicKey.toString()); expect(info.supplyKey.toString()).to.eql(key4.publicKey.toString()); expect(info.pauseKey.toString()).to.eql(key5.publicKey.toString()); - expect(info.metadataKey.toString()).to.eql(metadataKey.publicKey.toString()); + expect(info.metadataKey.toString()).to.eql( + metadataKey.publicKey.toString(), + ); expect(info.metadata).to.eql(metadata); expect(info.defaultFreezeStatus).to.be.false; expect(info.defaultKycStatus).to.be.false; @@ -105,7 +107,9 @@ describe("TokenUpdate", function () { expect(info.freezeKey.toString()).to.eql(key2.publicKey.toString()); expect(info.wipeKey.toString()).to.eql(key3.publicKey.toString()); expect(info.supplyKey.toString()).to.eql(key4.publicKey.toString()); - expect(info.metadataKey.toString()).to.eql(newMetadataKey.publicKey.toString()); + expect(info.metadataKey.toString()).to.eql( + newMetadataKey.publicKey.toString(), + ); expect(info.metadata).to.eql(metadata); expect(info.defaultFreezeStatus).to.be.false; expect(info.defaultKycStatus).to.be.false; From 89bc33cda48759f63a141b1d1cd63c8ced318c0b Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Fri, 19 Apr 2024 11:26:49 +0300 Subject: [PATCH 22/30] chore: network tag Signed-off-by: svetoslav-nikol0v --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 80880a35a..5ebb9fc7d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -102,7 +102,7 @@ jobs: id: start-local-node if: ${{ steps.build-sdk.conclusion == 'success' && !cancelled() && always() }} run: | - npx @hashgraph/hedera-local start -d —network-tag=0.49.0-alpha.4 --balance=100000 + npx @hashgraph/hedera-local start -d -—network-tag=0.49.0-alpha.4 --balance=100000 # Wait for the network to fully start sleep 30 From ee6053e2ff9151dcddd50c32c7b9316ed7c26cb8 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Mon, 22 Apr 2024 09:59:15 +0300 Subject: [PATCH 23/30] update: examples Signed-off-by: svetoslav-nikol0v --- examples/update-fungible-token-metadata-with-admin-key.js | 8 ++++---- .../update-fungible-token-metadata-with-metadata-key.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/update-fungible-token-metadata-with-admin-key.js b/examples/update-fungible-token-metadata-with-admin-key.js index 9d6f1ec3c..8e98eb5d8 100644 --- a/examples/update-fungible-token-metadata-with-admin-key.js +++ b/examples/update-fungible-token-metadata-with-admin-key.js @@ -30,8 +30,8 @@ async function main() { const network = process.env.HEDERA_NETWORK; const client = Client.forName(network).setOperator(operatorId, operatorKey); - // Generate a supply key - const adminKey = PrivateKey.fromStringDer(process.env.OPERATOR_KEY); + // Generate a admin key + const adminKey = PrivateKey.generateED25519(); // Initial metadata const metadata = new Uint8Array([1]); // New metadata @@ -45,7 +45,7 @@ async function main() { .setTokenName("Test") .setTokenSymbol("T") .setMetadata(metadata) - .setTokenType(TokenType.FungibleCommon) // Can be TokenType.NonFungibleUnique as well [HIP-765] + .setTokenType(TokenType.FungibleCommon) // The same flow can be executed with a TokenType.NON_FUNGIBLE_UNIQUE (i.e. HIP-765) .setDecimals(3) .setInitialSupply(10000) .setTreasuryAccountId(operatorId) @@ -54,7 +54,7 @@ async function main() { // Sign and execute create token transaction const tokenCreateTxResponse = await ( - await createTokenTx.sign(operatorKey) + await createTokenTx.sign(adminKey) ).execute(client); // Get receipt for create token transaction diff --git a/examples/update-fungible-token-metadata-with-metadata-key.js b/examples/update-fungible-token-metadata-with-metadata-key.js index 843cadc67..81ce5a8c9 100644 --- a/examples/update-fungible-token-metadata-with-metadata-key.js +++ b/examples/update-fungible-token-metadata-with-metadata-key.js @@ -45,7 +45,7 @@ async function main() { .setTokenName("Test") .setTokenSymbol("T") .setMetadata(metadata) - .setTokenType(TokenType.FungibleCommon) // Can be TokenType.NonFungibleUnique as well [HIP-765] + .setTokenType(TokenType.FungibleCommon) // The same flow can be executed with a TokenType.NON_FUNGIBLE_UNIQUE (i.e. HIP-765) .setDecimals(3) .setInitialSupply(10000) .setTreasuryAccountId(operatorId) From 21deae36561d727cd126949457783b9a7298ce87 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Mon, 22 Apr 2024 17:35:17 +0300 Subject: [PATCH 24/30] chore: test change Signed-off-by: svetoslav-nikol0v --- examples/update-nfts-metadata-of-non-fungible-token.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/update-nfts-metadata-of-non-fungible-token.js b/examples/update-nfts-metadata-of-non-fungible-token.js index 33ef782f6..3c5d515ea 100644 --- a/examples/update-nfts-metadata-of-non-fungible-token.js +++ b/examples/update-nfts-metadata-of-non-fungible-token.js @@ -38,7 +38,7 @@ async function main() { // Generate a metadata key const metadataKey = PrivateKey.generateED25519(); - // Generate a metadata key + // Generate a supply key const supplyKey = PrivateKey.generateED25519(); // Initial metadata const metadata = new Uint8Array([1]); From a18b596965888a0e3596352a2db907801b8fd4f4 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Tue, 23 Apr 2024 10:11:27 +0300 Subject: [PATCH 25/30] chore: update network tag 0.49.0-alpha.5 Signed-off-by: svetoslav-nikol0v --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5ebb9fc7d..000716fb3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -102,7 +102,7 @@ jobs: id: start-local-node if: ${{ steps.build-sdk.conclusion == 'success' && !cancelled() && always() }} run: | - npx @hashgraph/hedera-local start -d -—network-tag=0.49.0-alpha.4 --balance=100000 + npx @hashgraph/hedera-local start -d -—network-tag=0.49.0-alpha.5 --balance=100000 # Wait for the network to fully start sleep 30 From 98602ff9e96d53a2abfcd9e2c9d612f68a8a9ef7 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Wed, 24 Apr 2024 17:02:10 +0300 Subject: [PATCH 26/30] update: protobufs Signed-off-by: svetoslav-nikol0v --- packages/proto/src/proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/proto/src/proto b/packages/proto/src/proto index 98efa7c00..6d41db355 160000 --- a/packages/proto/src/proto +++ b/packages/proto/src/proto @@ -1 +1 @@ -Subproject commit 98efa7c00368b052cfffb91e5d72b47e3263965e +Subproject commit 6d41db35567c63073fd32be70cdae601a9e19aaf From 93c7e43035c1b72e1cfe57f74da5dc70f6e6efc5 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Wed, 24 Apr 2024 17:02:34 +0300 Subject: [PATCH 27/30] update: proto package version Signed-off-by: svetoslav-nikol0v --- packages/proto/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/proto/package.json b/packages/proto/package.json index 1b87cd3ab..324e4d2ab 100644 --- a/packages/proto/package.json +++ b/packages/proto/package.json @@ -1,6 +1,6 @@ { "name": "@hashgraph/proto", - "version": "2.14.0-beta.5", + "version": "2.14.0-beta.6", "description": "Protobufs for the Hedera™ Hashgraph SDK", "main": "lib/index.js", "browser": "src/index.js", @@ -67,4 +67,4 @@ "typescript": "^5.1.6", "protobufjs-cli": "^1.0.2" } -} +} \ No newline at end of file From be4ecab24cceae65290e97749e7d2324245279c0 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Wed, 24 Apr 2024 17:03:00 +0300 Subject: [PATCH 28/30] update: examples Signed-off-by: svetoslav-nikol0v --- examples/update-fungible-token-metadata-with-admin-key.js | 3 +-- examples/update-fungible-token-metadata-with-metadata-key.js | 3 +-- examples/update-nfts-metadata-of-non-fungible-token.js | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/update-fungible-token-metadata-with-admin-key.js b/examples/update-fungible-token-metadata-with-admin-key.js index 8e98eb5d8..c9031ea43 100644 --- a/examples/update-fungible-token-metadata-with-admin-key.js +++ b/examples/update-fungible-token-metadata-with-admin-key.js @@ -12,8 +12,7 @@ import dotenv from "dotenv"; dotenv.config(); /** - * @notice E2E-HIP-646 - * @url https://hips.hedera.com/hip/hip-646 + * @summary E2E-HIP-646 https://hips.hedera.com/hip/hip-646 * @description Update fungible token metadata with admin key */ async function main() { diff --git a/examples/update-fungible-token-metadata-with-metadata-key.js b/examples/update-fungible-token-metadata-with-metadata-key.js index 81ce5a8c9..99227d7d6 100644 --- a/examples/update-fungible-token-metadata-with-metadata-key.js +++ b/examples/update-fungible-token-metadata-with-metadata-key.js @@ -12,8 +12,7 @@ import dotenv from "dotenv"; dotenv.config(); /** - * @notice E2E-HIP-646 - * @url https://hips.hedera.com/hip/hip-646 + * @summary E2E-HIP-646 https://hips.hedera.com/hip/hip-646 * @description Update fungible token metadata with metadata key */ async function main() { diff --git a/examples/update-nfts-metadata-of-non-fungible-token.js b/examples/update-nfts-metadata-of-non-fungible-token.js index 3c5d515ea..3d33e9cf3 100644 --- a/examples/update-nfts-metadata-of-non-fungible-token.js +++ b/examples/update-nfts-metadata-of-non-fungible-token.js @@ -19,8 +19,8 @@ import dotenv from "dotenv"; dotenv.config(); /** - * @notice E2E-HIP-657 - * @url https://hips.hedera.com/hip/hip-657 + * @summary E2E-HIP-657 https://hips.hedera.com/hip/hip-657 + * @description Update nfts metadata of fungible token with metadata key */ async function main() { if ( From 68fa9c125783390044666552e89586f63559fac3 Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Wed, 24 Apr 2024 17:17:24 +0300 Subject: [PATCH 29/30] chore: formatting Signed-off-by: svetoslav-nikol0v --- test/integration/TokenUpdateIntegrationTest.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/integration/TokenUpdateIntegrationTest.js b/test/integration/TokenUpdateIntegrationTest.js index 087f06b8f..87a049722 100644 --- a/test/integration/TokenUpdateIntegrationTest.js +++ b/test/integration/TokenUpdateIntegrationTest.js @@ -322,7 +322,6 @@ describe("TokenUpdate", function () { const token = (await response.getReceipt(env.client)).tokenId; - try { await ( await new TokenUpdateTransaction() .setTokenId(token) @@ -333,7 +332,6 @@ describe("TokenUpdate", function () { } expect(status).to.be.eql(Status.TokenIsImmutable); - }); it("should error when admin key does not sign transaction", async function () { From 31f461274151c10b4646c891b98ed9600c761d0b Mon Sep 17 00:00:00 2001 From: svetoslav-nikol0v Date: Wed, 24 Apr 2024 17:54:42 +0300 Subject: [PATCH 30/30] update: codeowners Signed-off-by: svetoslav-nikol0v --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2a488605e..6347e9da6 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,2 @@ # Default code owners for entire repository -* @SimiHunjan @ochikov @petreze +* @SimiHunjan @ochikov @petreze @svetoslav-nikol0v @agadzhalov