From 486834161fa7a867bdbbc8c65484bf0fde9377f2 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Thu, 8 Aug 2024 09:45:39 -0500 Subject: [PATCH 01/25] feat: add tests up to custom fees Signed-off-by: Rob Walworth --- consensusInfoClient.js | 11 +- mirrorNodeClient.js | 5 + .../test_tokenCreateTransaction.js | 3002 +++++++++++++++++ 3 files changed, 3017 insertions(+), 1 deletion(-) create mode 100644 test/token-service/test_tokenCreateTransaction.js diff --git a/consensusInfoClient.js b/consensusInfoClient.js index 2f531b6..1a0674a 100644 --- a/consensusInfoClient.js +++ b/consensusInfoClient.js @@ -1,4 +1,4 @@ -import { AccountBalanceQuery, AccountId, AccountInfoQuery, Client, TokenCreateTransaction } from "@hashgraph/sdk"; +import { AccountBalanceQuery, AccountId, AccountInfoQuery, Client, TokenInfoQuery } from "@hashgraph/sdk"; class ConsensusInfoClient { constructor() { @@ -20,10 +20,19 @@ class ConsensusInfoClient { return this.executeAccountMethod(accountId, new AccountInfoQuery()); } + async getTokenInfo(tokenId) { + return this.executeTokenMethod(tokenId, new TokenInfoQuery()); + } + async executeAccountMethod(accountId, method) { method.setAccountId(accountId); return method.execute(this.sdkClient); } + + async executeTokenMethod(tokenId, method) { + method.setTokenId(tokenId); + return method.execute(this.sdkClient); + } } export default new ConsensusInfoClient(); diff --git a/mirrorNodeClient.js b/mirrorNodeClient.js index 23edf77..95ad901 100644 --- a/mirrorNodeClient.js +++ b/mirrorNodeClient.js @@ -16,6 +16,11 @@ class MirrorNodeClient { return this.retryUntilData(url, 'balances'); } + async getTokenData(tokenId) { + const url = `${this.mirrorNodeRestUrl}/api/v1/tokens?token.id=${tokenId}`; + return this.retryUntilData(url, 'tokens'); + } + async retryUntilData(url, dataKey) { const maxRetries = Math.floor(this.NODE_TIMEOUT / 1000); // retry once per second let retries = 0; diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js new file mode 100644 index 0000000..7e7a8fe --- /dev/null +++ b/test/token-service/test_tokenCreateTransaction.js @@ -0,0 +1,3002 @@ +import { JSONRPCRequest } from "../../client.js"; +import mirrorNodeClient from "../../mirrorNodeClient.js"; +import consensusInfoClient from "../../consensusInfoClient.js"; +import { setOperator } from "../../setup_Tests.js"; +import crypto from "crypto"; +import { assert, expect } from "chai"; + +/** + * Tests for AccountCreateTransaction + */ +describe("AccountCreateTransaction", function () { + // Tests should not take longer than 30 seconds to fully execute. + this.timeout(30000); + + // Each test should first establish the network to use, and then teardown the network when complete. + beforeEach(async function () { + await setOperator(process.env.OPERATOR_ACCOUNT_ID, process.env.OPERATOR_ACCOUNT_PRIVATE_KEY); + }); + afterEach(async function () { + await JSONRPCRequest("reset"); + }); + + describe("Name", function () { + async function verifyTokenCreationWithName(tokenId, name) { + // If the token was created successfully, the queried token's names should be equal. + expect(name).to.equal(await consensusInfoClient.getTokenInfo(tokenId).name); + expect(name).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].name); + } + + it("(#1) Creates a token with a name that is a valid length", async function () { + // Attempt to create a token with a name that is a valid length. + const name = "testname"; + const response = await JSONRPCRequest("createToken", { + name: name, + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Verify the token was created. + verifyTokenCreationWithName(response.tokenId, name); + }); + + it("(#2) Creates a token with a name that is the minimum length", async function () { + // Attempt to create a token with a name that is the minimum length. + const name = "t"; + const response = await JSONRPCRequest("createToken", { + name: name, + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Verify the token was created. + verifyTokenCreationWithName(response.tokenId, name); + }); + + it("(#3) Creates a token with a name that is empty", async function () { + try { + // Attempt to create a token with a name that is empty. The network should respond with a MISSING_TOKEN_NAME status. + const response = await JSONRPCRequest("createToken", { + name: "", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "MISSING_TOKEN_NAME"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#4) Creates a token with a name that is the maximum length", async function () { + // Attempt to create a token with a name that is the maximum length. + const name = "This is a really long name but it is still valid because it is 100 characters exactly on the money!!" + const response = await JSONRPCRequest("createToken", { + name: name, + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Verify the token was created. + verifyTokenCreationWithName(response.tokenId, name); + }); + + it("(#5) Creates a token with a name that exceeds the maximum length", async function () { + try { + // Attempt to create a token with a name that exceeds the maximum length. The network should respond with a TOKEN_NAME_TOO_LONG status. + const response = await JSONRPCRequest("createToken", { + name: "This is a long name that is not valid because it exceeds 100 characters and it should fail the test!!", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_NAME_TOO_LONG"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#6) Creates a token with no name", async function () { + try { + // Attempt to create a token with no name. The network should respond with a MISSING_TOKEN_NAME status. + const response = await JSONRPCRequest("createToken", { + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "MISSING_TOKEN_NAME"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Symbol", function () { + async function verifyTokenCreationWithSymbol(tokenId, symbol) { + // If the token was created successfully, the queried token's symbols should be equal. + expect(symbol).to.equal(await consensusInfoClient.getTokenInfo(tokenId).symbol); + expect(symbol).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].symbol); + } + + it("(#1) Creates a token with a symbol that is the minimum length", async function () { + // Attempt to create a token with a symbol that is the minimum length. + const symbol = "t"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: symbol, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Verify the token was created. + verifyTokenCreationWithSymbol(response.tokenId, symbol); + }); + + it("(#2) Creates a token with a symbol that is empty", async function () { + try { + // Attempt to create a token with a symbol that is empty. The network should respond with a MISSING_TOKEN_SYMBOL status. + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "MISSING_TOKEN_SYMBOL"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a token with a symbol that is the maximum length", async function () { + // Attempt to create a token with a symbol that is the maximum length. + const symbol = "This is a really long symbol but it is still valid because it is 100 characters exactly on the money"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: symbol, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Verify the token was created. + verifyTokenCreationWithSymbol(response.tokenId, symbol); + }); + + it("(#4) Creates a token with a symbol that exceeds the maximum length", async function () { + try { + // Attempt to create a token with a symbol that exceeds the maximum length. The network should respond with a TOKEN_SYMBOL_TOO_LONG status. + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "This is a long symbol that is not valid because it exceeds 100 characters and it should fail the test", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_SYMBOL_TOO_LONG"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#5) Creates a token with no symbol", async function () { + try { + // Attempt to create a token with no symbol. The network should respond with a MISSING_TOKEN_SYMBOL status. + const response = await JSONRPCRequest("createToken", { + name: "testname", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "MISSING_TOKEN_SYMBOL"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Decimals", function () { + async function verifyTokenCreationWithDecimals(tokenId, decimals) { + // If the token was created successfully, the queried token's decimals should be equal. + expect(decimals).to.equal(await consensusInfoClient.getTokenInfo(tokenId).decimals); + expect(decimals).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].decimals); + } + + it("(#1) Creates a fungible token with a valid amount of decimals", async function () { + // Attempt to create a token with a valid amount of decimals. + const decimals = 3; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Verify the token was created. + verifyTokenCreationWithDecimals(response.tokenId, decimals); + }); + + it("(#2) Creates a fungible token with the minimum amount of decimals", async function () { + // Attempt to create a token with the minimum amount of decimals. + const decimals = 0; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Verify the token was created. + verifyTokenCreationWithDecimals(response.tokenId, decimals); + }); + + it("(#3) Creates a fungible token with a decimal amount below the minimum amount", async function () { + try { + // Attempt to create a token with a decimal amount below the minimum amount. The network should respond with a INVALID_TOKEN_DECIMALS status. + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: -1, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#4) Creates a fungible token with the maximum amount of decimals", async function () { + // Attempt to create a token with the maximum amount of decimals. + const decimals = 2147483647; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Verify the token was created. + verifyTokenCreationWithDecimals(response.tokenId, decimals); + }); + + it("(#5) Creates a fungible token with a decimal amount that exceeds the maximum amount", async function () { + try { + // Attempt to create a token with a decimal amount that exceeds the maximum amount. The network should respond with a INVALID_TOKEN_DECIMALS status. + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: 2147483648, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#6) Creates an NFT with a decimal amount of zero", async function () { + try { + // Attempt to create an NFT with a decimal amount of zero. The network should respond with a TOKEN_HAS_NO_SUPPLY_KEY status. + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: 0, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#7) Creates an NFT with a nonzero decimal amount", async function () { + try { + // Attempt to create an NFT with a nonzero decimal amount. The network should respond with a INVALID_TOKEN_DECIMALS status. + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: 3, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Initial Supply", function () { + async function verifyTokenCreationWithInitialSupply(tokenId, initialSupply) { + expect(initialSupply).to.equal(await consensusInfoClient.getTokenInfo(tokenId).totalSupply); + expect(initialSupply).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].initial_supply); + } + + it("(#1) Creates a fungible token with a valid initial supply", async function () { + const initialSupply = 1000000; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: initialSupply, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); + }); + + it("(#2) Creates a fungible token with the minimum initial supply", async function () { + const initialSupply = 0; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: initialSupply, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); + }); + + it("(#3) Creates a fungible token with an initial supply below the minimum amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: -1, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#4) Creates a fungible token with the maximum initial supply", async function () { + const initialSupply = 9223372036854775807; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: initialSupply, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); + }); + + it("(#5) Creates a fungible token with an initial supply that exceeds the maximum amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: 9223372036854775808, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#6) Creates an NFT with an initial supply of zero", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: 0, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#7) Creates an NFT with a nonzero initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: 3, + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Treasury Account", function () { + async function verifyTokenCreationWithTreasuryAccount(tokenId, treasuryAccount) { + expect(treasuryAccount).to.equal(await consensusInfoClient.getTokenInfo(tokenId).treasuryAccountId.toString()); + expect(treasuryAccount).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].treasury_account_id); + } + + it("(#1) Creates a token with a treasury account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: accountId, + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithTreasuryAccount(response.tokenId, accountId); + }); + + it("(#2) Creates a token with a treasury account without signing with the account's private key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: accountId + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a token with a treasury account that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: "123.456.789" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_ACCOUNT_ID"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#4) Creates a token with a treasury account that is deleted", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: accountId + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TREASURY_ACCOUNT_FOR_TOKEN"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Admin Key", function () { + async function verifyTokenCreationWithAdminKey(tokenId, adminKey) { + expect(adminKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).adminKey.toStringDer()); + expect(adminKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].admin_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its admin key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + adminKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its admin key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + adminKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its admin key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + adminKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its admin key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + adminKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { + const keyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + } + ] + }); + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + adminKey: keyList.key, + commonTransactionParams: { + signers: [ + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithAdminKey(response.tokenId, keyList.key); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its admin key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + adminKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithAdminKey(response.tokenId, nestedKeyList.key); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + adminKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithAdminKey(response.tokenId, thresholdKey.key); + }); + + it("(#8) Creates a token with a valid key as its admin key but doesn't sign with it", async function () { + const key = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + if (key.status === "NOT_IMPLEMENTED") this.skip(); + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + adminKey: key.key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with an invalid key as its admin key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + adminKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("KYC Key", function () { + async function verifyTokenCreationWithKycKey(tokenId, kycKey) { + expect(kycKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).kycKey.toStringDer()); + expect(kycKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].kyc_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + kycKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + kycKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + kycKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + kycKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { + const keyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + } + ] + }); + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + kycKey: keyList.key, + commonTransactionParams: { + signers: [ + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithKycKey(response.tokenId, keyList.key); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its KYC key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + kycKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithKycKey(response.tokenId, nestedKeyList.key); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + kycKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithKycKey(response.tokenId, thresholdKey.key); + }); + + it("(#8) Creates a token with a valid key as its KYC key but doesn't sign with it", async function () { + const key = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + if (key.status === "NOT_IMPLEMENTED") this.skip(); + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + kycKey: key.key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with an invalid key as its KYC key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + kycKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Freeze Key", function () { + async function verifyTokenCreationWithFreezeKey(tokenId, freezeKey) { + expect(freezeKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).freezeKey.toStringDer()); + expect(freezeKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].freeze_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { + const keyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + } + ] + }); + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: keyList.key, + commonTransactionParams: { + signers: [ + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFreezeKey(response.tokenId, keyList.key); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its freeze key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFreezeKey(response.tokenId, nestedKeyList.key); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFreezeKey(response.tokenId, thresholdKey.key); + }); + + it("(#8) Creates a token with a valid key as its freeze key but doesn't sign with it", async function () { + const key = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + if (key.status === "NOT_IMPLEMENTED") this.skip(); + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: key.key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with an invalid key as its freeze key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Wipe Key", function () { + async function verifyTokenCreationWithWipeKey(tokenId, wipeKey) { + expect(wipeKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).wipeKey.toStringDer()); + expect(wipeKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].wipe_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { + const keyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + } + ] + }); + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: keyList.key, + commonTransactionParams: { + signers: [ + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithWipeKey(response.tokenId, keyList.key); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its wipe key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithWipeKey(response.tokenId, nestedKeyList.key); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithWipeKey(response.tokenId, thresholdKey.key); + }); + + it("(#8) Creates a token with a valid key as its wipe key but doesn't sign with it", async function () { + const key = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + if (key.status === "NOT_IMPLEMENTED") this.skip(); + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: key.key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with an invalid key as its wipe key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Supply Key", function () { + async function verifyTokenCreationWithSupplyKey(tokenId, supplyKey) { + expect(supplyKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).supplyKey.toStringDer()); + expect(supplyKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].supply_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { + const keyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + } + ] + }); + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: keyList.key, + commonTransactionParams: { + signers: [ + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithSupplyKey(response.tokenId, keyList.key); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its supply key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithSupplyKey(response.tokenId, nestedKeyList.key); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithSupplyKey(response.tokenId, thresholdKey.key); + }); + + it("(#8) Creates a token with a valid key as its supply key but doesn't sign with it", async function () { + const key = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + if (key.status === "NOT_IMPLEMENTED") this.skip(); + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key.key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with an invalid key as its supply key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Freeze Default", function () { + async function verifyTokenCreationWithFreezeDefault(tokenId, freezeDefault) { + expect(freezeDefault).to.equal(await consensusInfoClient.getTokenInfo(tokenId).freezeDefault); + expect(freezeDefault).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].freeze_default); + } + + it("(#1) Creates a token with a frozen default status", async function () { + const freezeDefault = true; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + freezeDefault: freezeDefault + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFreezeDefault(response.tokenId, freezeDefault); + }); + + it("(#2) Creates a token with an unfrozen default status", async function () { + const freezeDefault = false; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + freezeDefault: freezeDefault + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFreezeDefault(response.tokenId, freezeDefault); + }); + }); + + describe("Expiration Time", function () { + it("(#1) Creates a token with a valid expiration time", async function () { + const expirationTimeSeconds = (Date.now() / 1000) + 5184000; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: expirationTimeSeconds + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + expect(expirationTime).to.equal(await consensusInfoClient.getTokenInfo(tokenId).expirationTime); + expect(expirationTime).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].expiry_timestamp); + }); + + it("(#2) Creates a token with an expiration time of one less than the current time", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: (Date.now() / 1000) - 1 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a token with an expiration time 8,000,002 seconds from the current time", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: (Date.now() / 1000) - 8000002 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Auto Renew Account", function () { + it ("(#1) Creates a token with an auto renew account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccount: accountId + }); + + expect(autoRenewAccount).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewAccountId.toString()); + expect(autoRenewAccount).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_account); + }); + + it ("(#2) Creates a token with an auto renew account that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccount: "123.456.789" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it ("(#3) Creates a token with an empty auto renew account", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccount: "" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it ("(#4) Creates a token with an auto renew account that is deleted", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccount: accountId + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Auto Renew Period", function () { + async function verifyTokenCreationWithAutoRenewPeriod(tokenId, autoRenewPeriod) { + expect(autoRenewPeriod).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewPeriod); + expect(autoRenewPeriod).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_period); + } + + it ("(#1) Creates a token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { + const autoRenewPeriod = 5184000 + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: autoRenewPeriod + }); + + verifyTokenCreationWithAutoRenewPeriod(response.tokenId, autoRenewPeriod); + }); + + it ("(#2) Creates a token with an auto renew period set to -1 seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: -1 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it ("(#3) Creates a token with an auto renew period set to the minimum period of 30 days (2,592,000 seconds)", async function () { + const autoRenewPeriod = 2592000; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: autoRenewPeriod + }); + + verifyTokenCreationWithAutoRenewPeriod(response.tokenId, autoRenewPeriod); + }); + + it ("(#4) Creates a token with an auto renew period set to the minimum period of 30 days minus one second (2,591,999 seconds)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: 2591999 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it ("(#5) Creates a token with an auto renew period set to the maximum period of 8,000,001 seconds", async function () { + const autoRenewPeriod = 8000001; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: autoRenewPeriod + }); + + verifyTokenCreationWithAutoRenewPeriod(response.tokenId, autoRenewPeriod); + }); + + it ("(#6) Creates a token with an auto renew period set to the maximum period plus one second (8,000,002 seconds)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: 8000002 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Memo", function () { + async function verifyTokenCreationWithMemo(tokenId, memo) { + expect(memo).to.equal(await consensusInfoClient.getTokenInfo(tokenId).memo); + expect(memo).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].memo); + } + + it ("(#1) Creates a token with a memo that is a valid length", async function () { + const memo = "testmemo" + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + memo: memo + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMemo(response.tokenId, memo); + }); + + it ("(#2) Creates a token with a memo that is the minimum length", async function () { + const memo = "" + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + memo: memo + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMemo(response.tokenId, memo); + }); + + it ("(#3) Creates a token with a memo that is the maximum length", async function () { + const memo = "This is a really long memo but it is still valid because it is 100 characters exactly on the money!!" + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + memo: memo + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMemo(response.tokenId, memo); + }); + + it ("(#4) Creates a token with a memo that exceeds the maximum length", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + memo: "This is a long memo that is not valid because it exceeds 100 characters and it should fail the test!!" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "MEMO_TOO_LONG"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Token Type", function () { + async function verifyTokenCreationWithTokenType(tokenId, type) { + expect(type).to.equal(await consensusInfoClient.getTokenInfo(tokenId).type); + expect(type).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].type); + } + + it ("(#1) Creates a fungible token", async function () { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "ft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithTokenType(response.tokenId, "FUNGIBLE_COMMON"); + }); + + it ("(#2) Creates an NFT", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + });; + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithTokenType(response.tokenId, "NON_FUNGIBLE_UNIQUE"); + }); + + it ("(#3) Creates an NFT without a supply key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Supply Type", function () { + async function verifyTokenCreationWithSupplyType(tokenId, type) { + expect(type).to.equal(await consensusInfoClient.getTokenInfo(tokenId).supplyType); + expect(type).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].supply_type); + } + + it ("(#1) Creates a token with a finite supply", async function () { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "finite" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithSupplyType(response.tokenId, "FINITE"); + }) + + it ("(#2) Creates a token with an infinite supply", async function () { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "infinite" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithSupplyType(response.tokenId, "INFINITE"); + }) + }); + + describe("Max Supply", function () { + async function verifyTokenCreationWithMaxSupply(tokenId, maxSupply) { + expect(maxSupply).to.equal(await consensusInfoClient.getTokenInfo(tokenId).maxSupply); + expect(maxSupply).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].max_supply); + } + + it("(#1) Creates a fungible token with a valid max supply", async function () { + const maxSupply = 1000000; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: maxSupply + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); + }); + + it("(#2) Creates a fungible token with the minimum max supply", async function () { + const maxSupply = 1; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: maxSupply + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); + }); + + it("(#3) Creates a fungible token with a max supply below the minimum amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: 0 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#4) Creates a fungible token with the maximum max supply", async function () { + const maxSupply = 9223372036854775807; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: maxSupply + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); + }); + + it("(#5) Creates a fungible token with a max supply that exceeds the maximum amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: 9223372036854775808 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#6) Creates a fungible token with a max supply and an infinite supply type", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + maxSupply: 1000000 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#7) Creates an NFT with an max supply of zero", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + supplyType: "infinite", + tokenType: "nft", + maxSupply: 0 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#8) Creates an NFT with a nonzero max supply", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const maxSupply = 1000000; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + supplyType: "finite", + tokenType: "nft", + maxSupply: maxSupply + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); + }); + }); + + describe("Fee Schedule Key", function () { + async function verifyTokenCreationWithFeeScheduleKey(tokenId, feeScheduleKey) { + expect(feeScheduleKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).feeScheduleKey.toStringDer()); + expect(feeScheduleKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].fee_schedule_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { + const keyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + } + ] + }); + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: keyList.key, + commonTransactionParams: { + signers: [ + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFeeScheduleKey(response.tokenId, keyList.key); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its fee schedule key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFeeScheduleKey(response.tokenId, nestedKeyList.key); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFeeScheduleKey(response.tokenId, thresholdKey.key); + }); + + it("(#8) Creates a token with a valid key as its fee schedule key but doesn't sign with it", async function () { + const key = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + if (key.status === "NOT_IMPLEMENTED") this.skip(); + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: key.key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with an invalid key as its fee schedule key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Custom Fees", function (){ + async function verifyTokenCreationWithFixedFee(tokenId, amount) { + const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); + const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId).tokens[0]; + + expect(feeScheduleKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).feeScheduleKey.toStringDer()); + expect(feeScheduleKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].fee_schedule_key); + } + + it("(#1) Creates a token with a fixed fee", async function () { + let response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + amount: 10 + } + } + }); + }); + }); + + return Promise.resolve(); +}); From 6496dff5f43c398b3a244e7c861f3b0d82cfcb7a Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Fri, 9 Aug 2024 11:09:08 -0500 Subject: [PATCH 02/25] feat: first draft of all tests Signed-off-by: Rob Walworth --- .../test_tokenCreateTransaction.js | 1744 ++++++++++++++++- 1 file changed, 1734 insertions(+), 10 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index 7e7a8fe..b4fd786 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -4,6 +4,7 @@ import consensusInfoClient from "../../consensusInfoClient.js"; import { setOperator } from "../../setup_Tests.js"; import crypto from "crypto"; import { assert, expect } from "chai"; +import { CustomFixedFee, CustomFractionalFee } from "@hashgraph/sdk"; /** * Tests for AccountCreateTransaction @@ -2973,28 +2974,1751 @@ describe("AccountCreateTransaction", function () { }); }); - describe("Custom Fees", function (){ - async function verifyTokenCreationWithFixedFee(tokenId, amount) { + describe("Custom Fees", function () { + async function consensusNodeFeeEqualsCustomFee(customFee, feeCollectorAccountId, feeCollectorsExempt) { + return feeCollectorAccountId === customFee.feeCollectorAccountId.toString() && + feeCollectorsExempt === customFee.allCollectorsAreExempt; + } + + async function consensusNodeFeeEqualsCustomFixedFee(customFixedFee, feeCollectorAccountId, feeCollectorsExempt, amount) { + return consensusNodeFeeEqualsCustomFee(customFixedFee, feeCollectorAccountId, feeCollectorsExempt) && + amount === customFixedFee.amount; + } + + async function consensusNodeFeeEqualsCustomFractionalFee(customFractionalFee, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod) { + return consensusNodeFeeEqualsCustomFee(customFractionalFee, feeCollectorAccountId, feeCollectorsExempt) && + numerator === customFractionalFee.numerator && + denominator === customFractionalFee.denominator && + minAmount === customFractionalFee.minimumAmount && + maxAmount === customFractionalFee.maximumAmount && + assessmentMethod === customFractionalFee.assessmentMethod.toString().toLowerCase(); + } + + async function consensusNodeFeeEqualsCustomRoyaltyFee(customRoyaltyFee, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeCollectorAccountId, fixedFeeCollectorsExempt, fixedFeeAmount) { + return consensusNodeFeeEqualsCustomFee(customRoyaltyFee, feeCollectorAccountId, feeCollectorsExempt) && + numerator === customRoyaltyFee.numerator && + denominator === customRoyaltyFee.denominator && + consensusNodeFeeEqualsCustomFixedFee(customRoyaltyFee.fallbackFee, fixedFeeCollectorAccountId, fixedFeeCollectorsExempt, fixedFeeAmount); + } + + async function mirrorNodeFeeEqualsCustomFixedFee(customFixedFee, feeCollectorAccountId, amount) { + return feeCollectorAccountId === customFixedFee.collector_account_id && + amount === customFixedFee.amount; + } + + async function mirrorNodeFeeEqualsCustomFractionalFee(customFractionalFee, feeCollectorAccountId, numerator, denominator, minAmount, maxAmount, assessmentMethod) { + return feeCollectorAccountId === customFractionalFee.collector_account_id && + numerator === customFractionalFee.amount.numerator && + denominator === customFractionalFee.amount.denominator && + minAmount === customFractionalFee.minimum && + maxAmount === customFractionalFee.maximum && + ((assessmentMethod === "exclusive") === customFractionalFee.net_of_transfer); + } + + async function mirrorNodeFeeEqualsCustomRoyaltyFee(customRoyaltyFee, feeCollectorAccountId, numerator, denominator, fixedFeeAmount) { + return feeCollectorAccountId === customRoyaltyFee.collector_account_id && + numerator === customRoyaltyFee.amount.numerator && + denominator === customRoyaltyFee.amount.denominator && + fixedFeeAmount === customRoyaltyFee.fallback_fee.amount; + } + + async function verifyTokenCreationWithFixedFee(tokenId, feeCollectorAccountId, feeCollectorsExempt, amount) { const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId).tokens[0]; + + let foundConsensusNodeFee = false; + let foundMirrorNodeFee = false; + + for (let i = 0; i < consensusNodeInfo.customFees.size(); i++) { + if (consensusNodeInfo.customFees[i] instanceof CustomFixedFee && + consensusNodeFeeEqualsCustomFixedFee(consensusNodeInfo.customFees[i], feeCollectorAccountId, feeCollectorsExempt, amount)) { + foundConsensusNodeFee = true; + break; + } + } + + for (let i = 0; i < mirrorNodeInfo.custom_fees.fixed_fees.size(); i++) { + if (mirrorNodeFeeEqualsCustomFixedFee(mirrorNodeInfo.custom_fees.fixed_fees[i], feeCollectorAccountId, amount)) { + foundMirrorNodeFee = true; + break; + } + } - expect(feeScheduleKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).feeScheduleKey.toStringDer()); - expect(feeScheduleKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].fee_schedule_key); + expect(foundConsensusNodeFee).to.be.true; + expect(foundMirrorNodeFee).to.be.true; + } + + async function verifyTokenCreationWithFractionalFee(tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod) { + const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); + const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId).tokens[0]; + + let foundConsensusNodeFee = false; + let foundMirrorNodeFee = false; + + for (let i = 0; i < consensusNodeInfo.customFees.size(); i++) { + if (consensusNodeInfo.customFees[i] instanceof CustomFractionalFee && + consensusNodeFeeEqualsCustomFractionalFee(consensusNodeInfo.customFees[i], feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod)) { + foundConsensusNodeFee = true; + break; + } + } + + for (let i = 0; i < mirrorNodeInfo.custom_fees.fractional_fees.size(); i++) { + if (mirrorNodeFeeEqualsCustomFractionalFee(mirrorNodeInfo.custom_fees.fractional_fees[i], feeCollectorAccountId, numerator, denominator, minAmount, maxAmount, assessmentMethod)) { + foundMirrorNodeFee = true; + break; + } + } + + expect(foundConsensusNodeFee).to.be.true; + expect(foundMirrorNodeFee).to.be.true; + } + + async function verifyTokenCreationWithRoyaltyFee(tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeCollectorAccountId, fixedFeeCollectorsExempt, fixedFeeAmount) { + const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); + const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId).tokens[0]; + + let foundConsensusNodeFee = false; + let foundMirrorNodeFee = false; + + for (let i = 0; i < consensusNodeInfo.customFees.size(); i++) { + if (consensusNodeInfo.customFees[i] instanceof CustomRoyaltyFee && + consensusNodeFeeEqualsCustomRoyaltyFee(consensusNodeInfo.customFees[i], feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeCollectorAccountId, fixedFeeCollectorsExempt, fixedFeeAmount)) { + foundConsensusNodeFee = true; + break; + } + } + + for (let i = 0; i < mirrorNodeInfo.custom_fees.fractional_fees.size(); i++) { + if (mirrorNodeFeeEqualsCustomRoyaltyFee(mirrorNodeInfo.custom_fees.fractional_fees[i], feeCollectorAccountId, numerator, denominator, fixedFeeAmount)) { + foundMirrorNodeFee = true; + break; + } + } + + expect(foundConsensusNodeFee).to.be.true; + expect(foundMirrorNodeFee).to.be.true; } it("(#1) Creates a token with a fixed fee", async function () { - let response = await JSONRPCRequest("createToken", { + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const amount = 10; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, amount); + }); + + it("(#2) Creates a token with a fractional fee", async function () { + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minAmount = 1; + const maxAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minAmount, + maximumAmount: maxAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + }); + + it("(#3) Creates a token with a royalty fee", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const amount = 10; + response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, - customFees: { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fee: { - amount: 10 + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + numerator: numerator, + denominator: denominator, + fallbackFee: { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + amount: amount + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, feeCollectorAccount, feeCollectorsExempt, amount); + }); + + it("(#4) Creates a token with a fee that has a fee collector account that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: { + feeCollectorAccount: "123.456.789", + feeCollectorsExempt: false, + fee: { + amount: 10 + } + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#5) Creates a token with a fee with an empty fee collector account", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: { + feeCollectorAccount: "", + feeCollectorsExempt: false, + fee: { + amount: 10 + } } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#6) Creates a token with a fee that has a deleted fee collector account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] } }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: { + feeCollectorAccount: accountId, + feeCollectorsExempt: false, + fee: { + amount: 10 + } + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "ACCOUNT_DELETED"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#7) Creates a token with a fixed fee with the minimum amount", async function () { + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const amount = 1; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, amount); + }); + + it("(#8) Creates a token with a fixed fee with the amount below the minimum amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + amount: 0 + } + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with a fixed fee with the maximum amount", async function () { + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const amount = parseInt(9223372036854775807); + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, amount); + }); + + it("(#10) Creates a token with a fixed fee with the amount above the maximum amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + amount: 9223372036854775808 + } + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#11) Creates a token with a fixed fee that is assessed with the created token", async function () { + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const amount = 10; + const denominatingTokenId = "0.0.0"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount, + denominatingTokenId: denominatingTokenId + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, amount); + }); + + it("(#12) Creates a token with a fixed fee that is assessed with a token that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + amount: 10, + denominatingTokenId: "123.456.789" + } + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#13) Creates a token with a fixed fee that is assessed with an empty token", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + amount: 10, + denominatingTokenId: "" + } + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#14) Creates a token with a fixed fee that is assessed with a deleted token", async function () { + let response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const tokenId = response.tokenId; + + response = await JSONRPCRequest("deleteToken", { + tokenId: tokenId + }) + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + amount: 10, + denominatingTokenId: tokenId + } + } + }); + } catch (err) { + assert.equal(err.code.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#15) Creates a token with a fractional fee with the minimum fractional amount", async function () { + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = parseInt(9223372036854775807); + const minAmount = 1; + const maxAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minAmount, + maximumAmount: maxAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + }); + + it("(#16) Creates a token with a fractional fee with the amount below the minimum fractional amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + numerator: 0, + denominator: 9223372036854775807, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#17) Creates a token with a fractional fee with the maximum fractional amount", async function () { + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = parseInt(9223372036854775807); + const denominator = 1; + const minAmount = 1; + const maxAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minAmount, + maximumAmount: maxAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + }); + + it("(#18) Creates a token with a fractional fee with the amount above the maximum fractional amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + numerator: parseInt(9223372036854775808), + denominator: 1, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#19) Creates a token with a fractional fee with the minimum minimum amount", async function () { + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minAmount = 0; + const maxAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minAmount, + maximumAmount: maxAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + }); + + it("(#20) Creates a token with a fractional fee with the minimum amount below the minimum amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + numerator: 1, + denominator: 10, + minimumAmount: -1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#21) Creates a token with a fractional fee with the maximum maximum amount", async function () { + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minAmount = 1; + const maxAmount = parseInt(9223372036854775807); + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minAmount, + maximumAmount: maxAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + }); + + it("(#22) Creates a token with a fractional fee with the maximum amount above the maximum amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: parseInt(9223372036854775808), + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#23) Creates a token with a fractional fee with the minimum amount higher than the maximum amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + numerator: 1, + denominator: 10, + minimumAmount: 10, + maximumAmount: 1, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#24) Creates a token with a fractional fee that is assessed to the receiver", async function () { + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minAmount = 1; + const maxAmount = 10; + const assessmentMethod = "exclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minAmount, + maximumAmount: maxAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + }); + + it("(#25) Creates a token with a royalty fee with the minimum fractional amount", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }) + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = parseInt(9223372036854775807); + const fallbackFeeAmount = 10; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + numerator: numerator, + denominator: denominator, + fallbackFee: { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + amount: fallbackFeeAmount + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, feeCollectorAccount, feeCollectorsExempt, fallbackFeeAmount); + }); + + it("(#26) Creates a token with a royalty fee with the amount below the minimum fractional amount", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + numerator: 0, + denominator: parseInt(9223372036854775807), + fallbackFee: { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#27) Creates a token with a royalty fee with the maximum fractional amount", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }) + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = parseInt(9223372036854775807); + const denominator = 1; + const fallbackFeeAmount = 10; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + numerator: numerator, + denominator: denominator, + fallbackFee: { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + amount: fallbackFeeAmount + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, feeCollectorAccount, feeCollectorsExempt, fallbackFeeAmount); + }); + + it("(#28) Creates a token with a royalty fee with the amount above the maximum fractional amount", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + numerator: parseInt(9223372036854775808), + denominator: 1, + fallbackFee: { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#29) Creates a fungible token with a royalty fee", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "CUSTOM_ROYALTY_FEE_ONLY_ALLOWED_FOR_NON_FUNGIBLE_UNIQUE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#30) Creates a token with more than the maximum amount of fees allowed", async function () { + const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const amount = 10; + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + }, + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + }, + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + }, + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + }, + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + }, + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + }, + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + }, + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + }, + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + }, + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + }, + { + feeCollectorAccount: feeCollectorAccount, + feeCollectorsExempt: feeCollectorsExempt, + fee: { + amount: amount + } + }, + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code.status, "CUSTOM_FEES_LIST_TOO_LONG"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Pause Key", function () { + async function verifyTokenCreationWithPauseKey(tokenId, pauseKey) { + expect(pauseKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).pauseKey.toStringDer()); + expect(pauseKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].pause_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { + const keyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + } + ] + }); + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: keyList.key, + commonTransactionParams: { + signers: [ + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithPauseKey(response.tokenId, keyList.key); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its pause key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithPauseKey(response.tokenId, nestedKeyList.key); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithPauseKey(response.tokenId, thresholdKey.key); + }); + + it("(#8) Creates a token with a valid key as its pause key but doesn't sign with it", async function () { + const key = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + if (key.status === "NOT_IMPLEMENTED") this.skip(); + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: key.key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with an invalid key as its pause key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Metadata", function () { + async function verifyTokenCreationWithMetadata(tokenId, metadata) { + expect(metadata).to.equal(await consensusInfoClient.getTokenInfo(tokenId).metadata); + expect(metadata).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].metadata); + } + + it("(#1) Creates a token with metadata", async function () { + const metadata = "1234"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + metadata: metadata + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMetadata(response.tokenId, metadata); + }); + + it("(#2) Creates a token with empty metadata", async function () { + const metadata = ""; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + metadata: metadata + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMetadata(response.tokenId, metadata); + }); + }); + + describe("Metadata Key", function () { + async function verifyTokenCreationWithMetadataKey(tokenId, metadataKey) { + expect(metadataKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).metadataKey.toStringDer()); + expect(metadataKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].metadata_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { + const keyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + } + ] + }); + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: keyList.key, + commonTransactionParams: { + signers: [ + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithPauseKey(response.tokenId, keyList.key); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its metadata key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithPauseKey(response.tokenId, nestedKeyList.key); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithPauseKey(response.tokenId, thresholdKey.key); + }); + + it("(#8) Creates a token with a valid key as its metadata key but doesn't sign with it", async function () { + const key = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + if (key.status === "NOT_IMPLEMENTED") this.skip(); + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: key.key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with an invalid key as its metadata key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); }); }); From 2abd4eaabc6223e29f58544fc7e86401dab474d7 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Wed, 28 Aug 2024 14:22:14 -0500 Subject: [PATCH 03/25] fix: test issues Signed-off-by: Rob Walworth --- .../test_tokenCreateTransaction.js | 537 +++++++++--------- 1 file changed, 273 insertions(+), 264 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index b4fd786..b892c36 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -4,12 +4,16 @@ import consensusInfoClient from "../../consensusInfoClient.js"; import { setOperator } from "../../setup_Tests.js"; import crypto from "crypto"; import { assert, expect } from "chai"; -import { CustomFixedFee, CustomFractionalFee } from "@hashgraph/sdk"; + +// Needed to convert BigInts to JSON number format. +BigInt.prototype.toJSON = function () { + return JSON.rawJSON(this.toString()) +} /** - * Tests for AccountCreateTransaction + * Tests for TokenCreateTransaction */ -describe("AccountCreateTransaction", function () { +describe("TokenCreateTransaction", function () { // Tests should not take longer than 30 seconds to fully execute. this.timeout(30000); @@ -20,7 +24,7 @@ describe("AccountCreateTransaction", function () { afterEach(async function () { await JSONRPCRequest("reset"); }); - +/* describe("Name", function () { async function verifyTokenCreationWithName(tokenId, name) { // If the token was created successfully, the queried token's names should be equal. @@ -34,7 +38,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: name, symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -48,7 +52,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: name, symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -62,7 +66,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -80,7 +84,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: name, symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -94,7 +98,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "This is a long name that is not valid because it exceeds 100 characters and it should fail the test!!", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -111,7 +115,7 @@ describe("AccountCreateTransaction", function () { // Attempt to create a token with no name. The network should respond with a MISSING_TOKEN_NAME status. const response = await JSONRPCRequest("createToken", { symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -137,7 +141,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: symbol, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -151,7 +155,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -169,7 +173,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: symbol, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -183,7 +187,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "This is a long symbol that is not valid because it exceeds 100 characters and it should fail the test", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -200,7 +204,7 @@ describe("AccountCreateTransaction", function () { // Attempt to create a token with no symbol. The network should respond with a MISSING_TOKEN_SYMBOL status. const response = await JSONRPCRequest("createToken", { name: "testname", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -227,7 +231,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", decimals: decimals, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -242,7 +246,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", decimals: decimals, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -257,7 +261,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", decimals: -1, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -276,7 +280,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", decimals: decimals, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -291,7 +295,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", decimals: 2147483648, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -310,7 +314,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", decimals: 0, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, tokenType: "nft" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -330,7 +334,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", decimals: 3, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, tokenType: "nft" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -356,7 +360,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", initialSupply: initialSupply, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -369,7 +373,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", initialSupply: initialSupply, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -382,7 +386,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", initialSupply: -1, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -395,12 +399,12 @@ describe("AccountCreateTransaction", function () { }); it("(#4) Creates a fungible token with the maximum initial supply", async function () { - const initialSupply = 9223372036854775807; + const initialSupply = 9223372036854775807n; // Workaround for javascript not allowing numbers over 2^53 - 1. const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", initialSupply: initialSupply, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -412,8 +416,8 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - initialSupply: 9223372036854775808, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + initialSupply: 9223372036854775808n, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -431,7 +435,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", initialSupply: 0, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, tokenType: "nft" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -450,7 +454,7 @@ describe("AccountCreateTransaction", function () { name: "testname", symbol: "testsymbol", initialSupply: 3, - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, tokenType: "nft" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -465,9 +469,9 @@ describe("AccountCreateTransaction", function () { }); describe("Treasury Account", function () { - async function verifyTokenCreationWithTreasuryAccount(tokenId, treasuryAccount) { - expect(treasuryAccount).to.equal(await consensusInfoClient.getTokenInfo(tokenId).treasuryAccountId.toString()); - expect(treasuryAccount).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].treasury_account_id); + async function verifyTokenCreationWithTreasuryAccount(tokenId, treasuryAccountId) { + expect(treasuryAccountId).to.equal(await consensusInfoClient.getTokenInfo(tokenId).treasuryAccountId.toString()); + expect(treasuryAccountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].treasury_account_id); } it("(#1) Creates a token with a treasury account", async function () { @@ -486,7 +490,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: accountId, + treasuryAccountId: accountId, commonTransactionParams: { signers: [ key @@ -515,7 +519,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: accountId + treasuryAccountId: accountId }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -532,7 +536,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: "123.456.789" + treasuryAccountId: "123.456.789" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -546,7 +550,7 @@ describe("AccountCreateTransaction", function () { it("(#4) Creates a token with a treasury account that is deleted", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PrivateKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -571,7 +575,12 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: accountId + treasuryAccountId: accountId, + commonTransactionParams: { + signers: [ + key + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -606,7 +615,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, adminKey: publicKey, commonTransactionParams: { signers: [ @@ -636,7 +645,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, adminKey: publicKey, commonTransactionParams: { signers: [ @@ -666,7 +675,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, adminKey: privateKey, commonTransactionParams: { signers: [ @@ -696,7 +705,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, adminKey: privateKey, commonTransactionParams: { signers: [ @@ -727,10 +736,10 @@ describe("AccountCreateTransaction", function () { }); if (keyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, adminKey: keyList.key, commonTransactionParams: { signers: [ @@ -786,10 +795,10 @@ describe("AccountCreateTransaction", function () { }); if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, adminKey: nestedKeyList.key, commonTransactionParams: { signers: [ @@ -825,10 +834,10 @@ describe("AccountCreateTransaction", function () { }); if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, adminKey: thresholdKey.key, commonTransactionParams: { signers: [ @@ -852,7 +861,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, adminKey: key.key }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -870,7 +879,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, adminKey: crypto.randomBytes(88).toString("hex") }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -883,7 +892,7 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); }); - +*/ describe("KYC Key", function () { async function verifyTokenCreationWithKycKey(tokenId, kycKey) { expect(kycKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).kycKey.toStringDer()); @@ -906,7 +915,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, kycKey: publicKey, commonTransactionParams: { signers: [ @@ -936,7 +945,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, kycKey: publicKey, commonTransactionParams: { signers: [ @@ -966,7 +975,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, kycKey: privateKey, commonTransactionParams: { signers: [ @@ -996,7 +1005,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, kycKey: privateKey, commonTransactionParams: { signers: [ @@ -1027,10 +1036,10 @@ describe("AccountCreateTransaction", function () { }); if (keyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, kycKey: keyList.key, commonTransactionParams: { signers: [ @@ -1086,10 +1095,10 @@ describe("AccountCreateTransaction", function () { }); if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, kycKey: nestedKeyList.key, commonTransactionParams: { signers: [ @@ -1125,10 +1134,10 @@ describe("AccountCreateTransaction", function () { }); if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, kycKey: thresholdKey.key, commonTransactionParams: { signers: [ @@ -1152,7 +1161,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, kycKey: key.key }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1170,7 +1179,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, kycKey: crypto.randomBytes(88).toString("hex") }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1183,7 +1192,7 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); }); - +/* describe("Freeze Key", function () { async function verifyTokenCreationWithFreezeKey(tokenId, freezeKey) { expect(freezeKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).freezeKey.toStringDer()); @@ -1206,7 +1215,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeKey: publicKey, commonTransactionParams: { signers: [ @@ -1236,7 +1245,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeKey: publicKey, commonTransactionParams: { signers: [ @@ -1266,7 +1275,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeKey: privateKey, commonTransactionParams: { signers: [ @@ -1296,7 +1305,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeKey: privateKey, commonTransactionParams: { signers: [ @@ -1330,7 +1339,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeKey: keyList.key, commonTransactionParams: { signers: [ @@ -1389,7 +1398,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeKey: nestedKeyList.key, commonTransactionParams: { signers: [ @@ -1428,7 +1437,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeKey: thresholdKey.key, commonTransactionParams: { signers: [ @@ -1452,7 +1461,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeKey: key.key }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1470,7 +1479,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeKey: crypto.randomBytes(88).toString("hex") }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1506,7 +1515,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, wipeKey: publicKey, commonTransactionParams: { signers: [ @@ -1536,7 +1545,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, wipeKey: publicKey, commonTransactionParams: { signers: [ @@ -1566,7 +1575,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, wipeKey: privateKey, commonTransactionParams: { signers: [ @@ -1596,7 +1605,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, wipeKey: privateKey, commonTransactionParams: { signers: [ @@ -1630,7 +1639,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, wipeKey: keyList.key, commonTransactionParams: { signers: [ @@ -1689,7 +1698,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, wipeKey: nestedKeyList.key, commonTransactionParams: { signers: [ @@ -1728,7 +1737,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, wipeKey: thresholdKey.key, commonTransactionParams: { signers: [ @@ -1752,7 +1761,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, wipeKey: key.key }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1770,7 +1779,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, wipeKey: crypto.randomBytes(88).toString("hex") }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1806,7 +1815,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: publicKey, commonTransactionParams: { signers: [ @@ -1836,7 +1845,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: publicKey, commonTransactionParams: { signers: [ @@ -1866,7 +1875,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: privateKey, commonTransactionParams: { signers: [ @@ -1896,7 +1905,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: privateKey, commonTransactionParams: { signers: [ @@ -1930,7 +1939,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: keyList.key, commonTransactionParams: { signers: [ @@ -1989,7 +1998,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: nestedKeyList.key, commonTransactionParams: { signers: [ @@ -2028,7 +2037,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: thresholdKey.key, commonTransactionParams: { signers: [ @@ -2052,7 +2061,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: key.key }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2070,7 +2079,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: crypto.randomBytes(88).toString("hex") }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2095,7 +2104,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeDefault: freezeDefault }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2108,7 +2117,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeDefault: freezeDefault }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2123,7 +2132,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, expirationTime: expirationTimeSeconds }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2137,7 +2146,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, expirationTime: (Date.now() / 1000) - 1 }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2155,7 +2164,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, expirationTime: (Date.now() / 1000) - 8000002 }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2186,12 +2195,12 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, - autoRenewAccount: accountId + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccountId: accountId }); - expect(autoRenewAccount).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewAccountId.toString()); - expect(autoRenewAccount).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_account); + expect(accountId).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewAccountId.toString()); + expect(accountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_account); }); it ("(#2) Creates a token with an auto renew account that doesn't exist", async function () { @@ -2199,8 +2208,8 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, - autoRenewAccount: "123.456.789" + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccountId: "123.456.789" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2217,8 +2226,8 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, - autoRenewAccount: "" + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccountId: "" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2258,8 +2267,8 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, - autoRenewAccount: accountId + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccountId: accountId }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2283,7 +2292,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: autoRenewPeriod }); @@ -2295,7 +2304,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: -1 }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2313,7 +2322,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: autoRenewPeriod }); @@ -2325,7 +2334,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: 2591999 }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2343,7 +2352,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: autoRenewPeriod }); @@ -2355,7 +2364,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: 8000002 }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2380,7 +2389,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, memo: memo }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2393,7 +2402,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, memo: memo }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2406,7 +2415,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, memo: memo }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2419,7 +2428,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, memo: "This is a long memo that is not valid because it exceeds 100 characters and it should fail the test!!" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2443,7 +2452,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, tokenType: "ft" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2461,7 +2470,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: key, tokenType: "nft" }); @@ -2475,7 +2484,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, tokenType: "nft" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2499,7 +2508,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, tokenType: "finite" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2511,7 +2520,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, tokenType: "infinite" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2531,7 +2540,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyType: "finite", maxSupply: maxSupply }); @@ -2545,7 +2554,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyType: "finite", maxSupply: maxSupply }); @@ -2559,7 +2568,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyType: "finite", maxSupply: 0 }); @@ -2578,7 +2587,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyType: "finite", maxSupply: maxSupply }); @@ -2592,7 +2601,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyType: "finite", maxSupply: 9223372036854775808 }); @@ -2611,7 +2620,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, maxSupply: 1000000 }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2635,7 +2644,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: key, supplyType: "infinite", tokenType: "nft", @@ -2662,7 +2671,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: key, supplyType: "finite", tokenType: "nft", @@ -2696,7 +2705,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, feeScheduleKey: publicKey, commonTransactionParams: { signers: [ @@ -2726,7 +2735,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, feeScheduleKey: publicKey, commonTransactionParams: { signers: [ @@ -2756,7 +2765,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, feeScheduleKey: privateKey, commonTransactionParams: { signers: [ @@ -2786,7 +2795,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, feeScheduleKey: privateKey, commonTransactionParams: { signers: [ @@ -2820,7 +2829,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, feeScheduleKey: keyList.key, commonTransactionParams: { signers: [ @@ -2879,7 +2888,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, feeScheduleKey: nestedKeyList.key, commonTransactionParams: { signers: [ @@ -2918,7 +2927,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, feeScheduleKey: thresholdKey.key, commonTransactionParams: { signers: [ @@ -2942,7 +2951,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, feeScheduleKey: key.key }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2960,7 +2969,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, feeScheduleKey: crypto.randomBytes(88).toString("hex") }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -3101,16 +3110,16 @@ describe("AccountCreateTransaction", function () { } it("(#1) Creates a token with a fixed fee", async function () { - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const amount = 10; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount @@ -3120,11 +3129,11 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, amount); + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); }); it("(#2) Creates a token with a fractional fee", async function () { - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; const denominator = 10; @@ -3134,10 +3143,10 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { numerator: numerator, @@ -3151,7 +3160,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); }); it("(#3) Creates a token with a royalty fee", async function () { @@ -3161,7 +3170,7 @@ describe("AccountCreateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; const denominator = 10; @@ -3169,18 +3178,18 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: key, tokenType: "nft", customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { numerator: numerator, denominator: denominator, fallbackFee: { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, amount: amount } @@ -3190,7 +3199,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, feeCollectorAccount, feeCollectorsExempt, amount); + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, amount); }); it("(#4) Creates a token with a fee that has a fee collector account that doesn't exist", async function () { @@ -3198,9 +3207,9 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: { - feeCollectorAccount: "123.456.789", + feeCollectorAccountId: "123.456.789", feeCollectorsExempt: false, fee: { amount: 10 @@ -3222,9 +3231,9 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: { - feeCollectorAccount: "", + feeCollectorAccountId: "", feeCollectorsExempt: false, fee: { amount: 10 @@ -3269,9 +3278,9 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: { - feeCollectorAccount: accountId, + feeCollectorAccountId: accountId, feeCollectorsExempt: false, fee: { amount: 10 @@ -3289,16 +3298,16 @@ describe("AccountCreateTransaction", function () { }); it("(#7) Creates a token with a fixed fee with the minimum amount", async function () { - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const amount = 1; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount @@ -3308,7 +3317,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, amount); + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); }); it("(#8) Creates a token with a fixed fee with the amount below the minimum amount", async function () { @@ -3316,9 +3325,9 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { amount: 0 @@ -3336,16 +3345,16 @@ describe("AccountCreateTransaction", function () { }); it("(#9) Creates a token with a fixed fee with the maximum amount", async function () { - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const amount = parseInt(9223372036854775807); const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount @@ -3355,7 +3364,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, amount); + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); }); it("(#10) Creates a token with a fixed fee with the amount above the maximum amount", async function () { @@ -3363,9 +3372,9 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { amount: 9223372036854775808 @@ -3383,17 +3392,17 @@ describe("AccountCreateTransaction", function () { }); it("(#11) Creates a token with a fixed fee that is assessed with the created token", async function () { - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const amount = 10; const denominatingTokenId = "0.0.0"; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount, @@ -3404,7 +3413,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, amount); + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); }); it("(#12) Creates a token with a fixed fee that is assessed with a token that doesn't exist", async function () { @@ -3412,9 +3421,9 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { amount: 10, @@ -3437,9 +3446,9 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { amount: 10, @@ -3461,7 +3470,7 @@ describe("AccountCreateTransaction", function () { let response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const tokenId = response.tokenId; @@ -3475,9 +3484,9 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { amount: 10, @@ -3495,7 +3504,7 @@ describe("AccountCreateTransaction", function () { }); it("(#15) Creates a token with a fractional fee with the minimum fractional amount", async function () { - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; const denominator = parseInt(9223372036854775807); @@ -3505,10 +3514,10 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { numerator: numerator, @@ -3522,7 +3531,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); }); it("(#16) Creates a token with a fractional fee with the amount below the minimum fractional amount", async function () { @@ -3530,10 +3539,10 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { numerator: 0, @@ -3556,7 +3565,7 @@ describe("AccountCreateTransaction", function () { }); it("(#17) Creates a token with a fractional fee with the maximum fractional amount", async function () { - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = parseInt(9223372036854775807); const denominator = 1; @@ -3566,10 +3575,10 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { numerator: numerator, @@ -3583,7 +3592,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); }); it("(#18) Creates a token with a fractional fee with the amount above the maximum fractional amount", async function () { @@ -3591,10 +3600,10 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { numerator: parseInt(9223372036854775808), @@ -3617,7 +3626,7 @@ describe("AccountCreateTransaction", function () { }); it("(#19) Creates a token with a fractional fee with the minimum minimum amount", async function () { - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; const denominator = 10; @@ -3627,10 +3636,10 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { numerator: numerator, @@ -3644,7 +3653,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); }); it("(#20) Creates a token with a fractional fee with the minimum amount below the minimum amount", async function () { @@ -3652,10 +3661,10 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { numerator: 1, @@ -3678,7 +3687,7 @@ describe("AccountCreateTransaction", function () { }); it("(#21) Creates a token with a fractional fee with the maximum maximum amount", async function () { - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; const denominator = 10; @@ -3688,10 +3697,10 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { numerator: numerator, @@ -3705,7 +3714,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); }); it("(#22) Creates a token with a fractional fee with the maximum amount above the maximum amount", async function () { @@ -3713,10 +3722,10 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { numerator: 1, @@ -3743,10 +3752,10 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { numerator: 1, @@ -3769,7 +3778,7 @@ describe("AccountCreateTransaction", function () { }); it("(#24) Creates a token with a fractional fee that is assessed to the receiver", async function () { - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; const denominator = 10; @@ -3779,10 +3788,10 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { numerator: numerator, @@ -3796,7 +3805,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); }); it("(#25) Creates a token with a royalty fee with the minimum fractional amount", async function () { @@ -3806,7 +3815,7 @@ describe("AccountCreateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; const denominator = parseInt(9223372036854775807); @@ -3814,18 +3823,18 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: key, tokenType: "nft", customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { numerator: numerator, denominator: denominator, fallbackFee: { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, amount: fallbackFeeAmount } @@ -3835,7 +3844,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, feeCollectorAccount, feeCollectorsExempt, fallbackFeeAmount); + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); }); it("(#26) Creates a token with a royalty fee with the amount below the minimum fractional amount", async function () { @@ -3849,18 +3858,18 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: key, tokenType: "nft", customFees: [ { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { numerator: 0, denominator: parseInt(9223372036854775807), fallbackFee: { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, amount: 10 } @@ -3885,7 +3894,7 @@ describe("AccountCreateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = parseInt(9223372036854775807); const denominator = 1; @@ -3893,18 +3902,18 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: key, tokenType: "nft", customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { numerator: numerator, denominator: denominator, fallbackFee: { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, amount: fallbackFeeAmount } @@ -3914,7 +3923,7 @@ describe("AccountCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccount, feeCollectorsExempt, numerator, denominator, feeCollectorAccount, feeCollectorsExempt, fallbackFeeAmount); + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); }); it("(#28) Creates a token with a royalty fee with the amount above the maximum fractional amount", async function () { @@ -3928,18 +3937,18 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: key, tokenType: "nft", customFees: [ { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { numerator: parseInt(9223372036854775808), denominator: 1, fallbackFee: { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, amount: 10 } @@ -3962,16 +3971,16 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fee: { numerator: 1, denominator: 10, fallbackFee: { - feeCollectorAccount: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, amount: 10 } @@ -3990,87 +3999,87 @@ describe("AccountCreateTransaction", function () { }); it("(#30) Creates a token with more than the maximum amount of fees allowed", async function () { - const feeCollectorAccount = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const amount = 10; try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount } }, { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount } }, { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount } }, { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount } }, { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount } }, { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount } }, { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount } }, { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount } }, { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount } }, { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount } }, { - feeCollectorAccount: feeCollectorAccount, + feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, fee: { amount: amount @@ -4111,7 +4120,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, pauseKey: publicKey, commonTransactionParams: { signers: [ @@ -4141,7 +4150,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, pauseKey: publicKey, commonTransactionParams: { signers: [ @@ -4171,7 +4180,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, pauseKey: privateKey, commonTransactionParams: { signers: [ @@ -4201,7 +4210,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, pauseKey: privateKey, commonTransactionParams: { signers: [ @@ -4235,7 +4244,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, pauseKey: keyList.key, commonTransactionParams: { signers: [ @@ -4294,7 +4303,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, pauseKey: nestedKeyList.key, commonTransactionParams: { signers: [ @@ -4333,7 +4342,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, pauseKey: thresholdKey.key, commonTransactionParams: { signers: [ @@ -4357,7 +4366,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, pauseKey: key.key }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -4375,7 +4384,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, pauseKey: crypto.randomBytes(88).toString("hex") }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -4400,7 +4409,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadata: metadata }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -4413,7 +4422,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadata: metadata }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -4444,7 +4453,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadataKey: publicKey, commonTransactionParams: { signers: [ @@ -4474,7 +4483,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadataKey: publicKey, commonTransactionParams: { signers: [ @@ -4504,7 +4513,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadataKey: privateKey, commonTransactionParams: { signers: [ @@ -4534,7 +4543,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadataKey: privateKey, commonTransactionParams: { signers: [ @@ -4568,7 +4577,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadataKey: keyList.key, commonTransactionParams: { signers: [ @@ -4627,7 +4636,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadataKey: nestedKeyList.key, commonTransactionParams: { signers: [ @@ -4666,7 +4675,7 @@ describe("AccountCreateTransaction", function () { response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadataKey: thresholdKey.key, commonTransactionParams: { signers: [ @@ -4690,7 +4699,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadataKey: key.key }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -4708,7 +4717,7 @@ describe("AccountCreateTransaction", function () { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - treasuryAccount: process.env.OPERATOR_ACCOUNT_ID, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadataKey: crypto.randomBytes(88).toString("hex") }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -4720,7 +4729,7 @@ describe("AccountCreateTransaction", function () { // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - }); + });*/ return Promise.resolve(); }); From 864c3fcc4b3c5865c08a695d6b25ff99069b3da9 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Wed, 28 Aug 2024 14:29:22 -0500 Subject: [PATCH 04/25] fix: kyc key doesn't need to sign tokencreate Signed-off-by: Rob Walworth --- .../test_tokenCreateTransaction.js | 96 ++++--------------- 1 file changed, 21 insertions(+), 75 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index b892c36..e8aaf3d 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -901,14 +901,7 @@ describe("TokenCreateTransaction", function () { it("(#1) Creates a token with a valid ED25519 public key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey", - fromKey: privateKey + type: "ed25519PublicKey" }); const publicKey = response.key; @@ -916,12 +909,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + kycKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -931,14 +919,7 @@ describe("TokenCreateTransaction", function () { it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + type: "ecdsaSecp256k1PublicKey" }); const publicKey = response.key; @@ -946,12 +927,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + kycKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -976,12 +952,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + kycKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1006,12 +977,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + kycKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1020,7 +986,7 @@ describe("TokenCreateTransaction", function () { }); it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { - const keyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1034,20 +1000,14 @@ describe("TokenCreateTransaction", function () { } ] }); - if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; - const response = await JSONRPCRequest("createToken", { + response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: keyList.key, - commonTransactionParams: { - signers: [ - keyList.privateKeys[0], - keyList.privateKeys[1], - keyList.privateKeys[2] - ] - } + kycKey: keyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1055,7 +1015,7 @@ describe("TokenCreateTransaction", function () { }); it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its KYC key", async function () { - const nestedKeyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1093,23 +1053,14 @@ describe("TokenCreateTransaction", function () { } ] }); - if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; - const response = await JSONRPCRequest("createToken", { + response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: nestedKeyList.key, - commonTransactionParams: { - signers: [ - nestedKeyList.privateKeys[0], - nestedKeyList.privateKeys[1], - nestedKeyList.privateKeys[2], - nestedKeyList.privateKeys[3], - nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + kycKey: nestedKeyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1117,7 +1068,7 @@ describe("TokenCreateTransaction", function () { }); it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { - const thresholdKey = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -1132,19 +1083,14 @@ describe("TokenCreateTransaction", function () { } ] }); - if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; - const response = await JSONRPCRequest("createToken", { + response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: thresholdKey.key, - commonTransactionParams: { - signers: [ - thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + kycKey: thresholdKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); From 808ec38d7f8904d423efa91dbb3511bfd11a840d Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Wed, 28 Aug 2024 15:35:04 -0500 Subject: [PATCH 05/25] fix: key tests Signed-off-by: Rob Walworth --- .../test_tokenCreateTransaction.js | 642 ++++-------------- 1 file changed, 117 insertions(+), 525 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index e8aaf3d..1be84d5 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -24,7 +24,7 @@ describe("TokenCreateTransaction", function () { afterEach(async function () { await JSONRPCRequest("reset"); }); -/* + describe("Name", function () { async function verifyTokenCreationWithName(tokenId, name) { // If the token was created successfully, the queried token's names should be equal. @@ -892,7 +892,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); }); -*/ + describe("KYC Key", function () { async function verifyTokenCreationWithKycKey(tokenId, kycKey) { expect(kycKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).kycKey.toStringDer()); @@ -1011,7 +1011,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithKycKey(response.tokenId, keyList.key); + verifyTokenCreationWithKycKey(response.tokenId, keyList); }); it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its KYC key", async function () { @@ -1064,7 +1064,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithKycKey(response.tokenId, nestedKeyList.key); + verifyTokenCreationWithKycKey(response.tokenId, nestedKeyList); }); it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { @@ -1094,33 +1094,10 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithKycKey(response.tokenId, thresholdKey.key); + verifyTokenCreationWithKycKey(response.tokenId, thresholdKey); }); - it("(#8) Creates a token with a valid key as its KYC key but doesn't sign with it", async function () { - const key = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" - }); - if (key.status === "NOT_IMPLEMENTED") this.skip(); - - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: key.key - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); - return; - } - - // The test failed, no error was thrown. - assert.fail("Should throw an error"); - }); - - it("(#9) Creates a token with an invalid key as its KYC key", async function () { + it("(#8) Creates a token with an invalid key as its KYC key", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -1138,7 +1115,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); }); -/* + describe("Freeze Key", function () { async function verifyTokenCreationWithFreezeKey(tokenId, freezeKey) { expect(freezeKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).freezeKey.toStringDer()); @@ -1147,14 +1124,7 @@ describe("TokenCreateTransaction", function () { it("(#1) Creates a token with a valid ED25519 public key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey", - fromKey: privateKey + type: "ed25519PublicKey" }); const publicKey = response.key; @@ -1162,12 +1132,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + freezeKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1177,14 +1142,7 @@ describe("TokenCreateTransaction", function () { it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + type: "ecdsaSecp256k1PublicKey" }); const publicKey = response.key; @@ -1192,12 +1150,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + freezeKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1222,12 +1175,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + freezeKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1252,12 +1200,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + freezeKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1266,7 +1209,7 @@ describe("TokenCreateTransaction", function () { }); it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { - const keyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1280,28 +1223,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: keyList.key, - commonTransactionParams: { - signers: [ - keyList.privateKeys[0], - keyList.privateKeys[1], - keyList.privateKeys[2] - ] - } + freezeKey: keyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFreezeKey(response.tokenId, keyList.key); + verifyTokenCreationWithFreezeKey(response.tokenId, keyList); }); it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its freeze key", async function () { - const nestedKeyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1339,31 +1276,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: nestedKeyList.key, - commonTransactionParams: { - signers: [ - nestedKeyList.privateKeys[0], - nestedKeyList.privateKeys[1], - nestedKeyList.privateKeys[2], - nestedKeyList.privateKeys[3], - nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + freezeKey: nestedKeyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFreezeKey(response.tokenId, nestedKeyList.key); + verifyTokenCreationWithFreezeKey(response.tokenId, nestedKeyList); }); it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { - const thresholdKey = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -1378,49 +1306,21 @@ describe("TokenCreateTransaction", function () { } ] }); - if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: thresholdKey.key, - commonTransactionParams: { - signers: [ - thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + freezeKey: thresholdKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFreezeKey(response.tokenId, thresholdKey.key); - }); - - it("(#8) Creates a token with a valid key as its freeze key but doesn't sign with it", async function () { - const key = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" - }); - if (key.status === "NOT_IMPLEMENTED") this.skip(); - - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: key.key - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); - return; - } - - // The test failed, no error was thrown. - assert.fail("Should throw an error"); + verifyTokenCreationWithFreezeKey(response.tokenId, thresholdKey); }); - it("(#9) Creates a token with an invalid key as its freeze key", async function () { + it("(#8) Creates a token with an invalid key as its freeze key", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -1447,14 +1347,7 @@ describe("TokenCreateTransaction", function () { it("(#1) Creates a token with a valid ED25519 public key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey", - fromKey: privateKey + type: "ed25519PublicKey" }); const publicKey = response.key; @@ -1462,12 +1355,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + wipeKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1477,14 +1365,7 @@ describe("TokenCreateTransaction", function () { it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + type: "ecdsaSecp256k1PublicKey" }); const publicKey = response.key; @@ -1492,12 +1373,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + wipeKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1522,12 +1398,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + wipeKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1552,12 +1423,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + wipeKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1566,7 +1432,7 @@ describe("TokenCreateTransaction", function () { }); it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { - const keyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1580,28 +1446,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: keyList.key, - commonTransactionParams: { - signers: [ - keyList.privateKeys[0], - keyList.privateKeys[1], - keyList.privateKeys[2] - ] - } + wipeKey: keyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithWipeKey(response.tokenId, keyList.key); + verifyTokenCreationWithWipeKey(response.tokenId, keyList); }); it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its wipe key", async function () { - const nestedKeyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1639,31 +1499,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: nestedKeyList.key, - commonTransactionParams: { - signers: [ - nestedKeyList.privateKeys[0], - nestedKeyList.privateKeys[1], - nestedKeyList.privateKeys[2], - nestedKeyList.privateKeys[3], - nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + wipeKey: nestedKeyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithWipeKey(response.tokenId, nestedKeyList.key); + verifyTokenCreationWithWipeKey(response.tokenId, nestedKeyList); }); it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { - const thresholdKey = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -1678,49 +1529,21 @@ describe("TokenCreateTransaction", function () { } ] }); - if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: thresholdKey.key, - commonTransactionParams: { - signers: [ - thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + wipeKey: thresholdKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithWipeKey(response.tokenId, thresholdKey.key); - }); - - it("(#8) Creates a token with a valid key as its wipe key but doesn't sign with it", async function () { - const key = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" - }); - if (key.status === "NOT_IMPLEMENTED") this.skip(); - - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: key.key - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); - return; - } - - // The test failed, no error was thrown. - assert.fail("Should throw an error"); + verifyTokenCreationWithWipeKey(response.tokenId, thresholdKey); }); - it("(#9) Creates a token with an invalid key as its wipe key", async function () { + it("(#8) Creates a token with an invalid key as its wipe key", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -1747,14 +1570,7 @@ describe("TokenCreateTransaction", function () { it("(#1) Creates a token with a valid ED25519 public key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey", - fromKey: privateKey + type: "ed25519PublicKey" }); const publicKey = response.key; @@ -1762,12 +1578,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + supplyKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1777,14 +1588,7 @@ describe("TokenCreateTransaction", function () { it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + type: "ecdsaSecp256k1PublicKey" }); const publicKey = response.key; @@ -1792,12 +1596,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + supplyKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1822,12 +1621,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + supplyKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1852,12 +1646,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + supplyKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1866,7 +1655,7 @@ describe("TokenCreateTransaction", function () { }); it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { - const keyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1880,28 +1669,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: keyList.key, - commonTransactionParams: { - signers: [ - keyList.privateKeys[0], - keyList.privateKeys[1], - keyList.privateKeys[2] - ] - } + supplyKey: keyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithSupplyKey(response.tokenId, keyList.key); + verifyTokenCreationWithSupplyKey(response.tokenId, keyList); }); it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its supply key", async function () { - const nestedKeyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1939,31 +1722,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: nestedKeyList.key, - commonTransactionParams: { - signers: [ - nestedKeyList.privateKeys[0], - nestedKeyList.privateKeys[1], - nestedKeyList.privateKeys[2], - nestedKeyList.privateKeys[3], - nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + supplyKey: nestedKeyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithSupplyKey(response.tokenId, nestedKeyList.key); + verifyTokenCreationWithSupplyKey(response.tokenId, nestedKeyList); }); it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { - const thresholdKey = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -1978,49 +1752,21 @@ describe("TokenCreateTransaction", function () { } ] }); - if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: thresholdKey.key, - commonTransactionParams: { - signers: [ - thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + supplyKey: thresholdKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); verifyTokenCreationWithSupplyKey(response.tokenId, thresholdKey.key); }); - it("(#8) Creates a token with a valid key as its supply key but doesn't sign with it", async function () { - const key = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" - }); - if (key.status === "NOT_IMPLEMENTED") this.skip(); - - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key.key - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); - return; - } - - // The test failed, no error was thrown. - assert.fail("Should throw an error"); - }); - - it("(#9) Creates a token with an invalid key as its supply key", async function () { + it("(#8) Creates a token with an invalid key as its supply key", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -2637,14 +2383,7 @@ describe("TokenCreateTransaction", function () { it("(#1) Creates a token with a valid ED25519 public key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey", - fromKey: privateKey + type: "ed25519PublicKey" }); const publicKey = response.key; @@ -2652,12 +2391,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + feeScheduleKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2667,14 +2401,7 @@ describe("TokenCreateTransaction", function () { it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + type: "ecdsaSecp256k1PublicKey" }); const publicKey = response.key; @@ -2682,12 +2409,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + feeScheduleKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2712,12 +2434,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + feeScheduleKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2742,12 +2459,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + feeScheduleKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2756,7 +2468,7 @@ describe("TokenCreateTransaction", function () { }); it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { - const keyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -2770,28 +2482,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: keyList.key, - commonTransactionParams: { - signers: [ - keyList.privateKeys[0], - keyList.privateKeys[1], - keyList.privateKeys[2] - ] - } + feeScheduleKey: keyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFeeScheduleKey(response.tokenId, keyList.key); + verifyTokenCreationWithFeeScheduleKey(response.tokenId, keyList); }); it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its fee schedule key", async function () { - const nestedKeyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -2829,31 +2535,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: nestedKeyList.key, - commonTransactionParams: { - signers: [ - nestedKeyList.privateKeys[0], - nestedKeyList.privateKeys[1], - nestedKeyList.privateKeys[2], - nestedKeyList.privateKeys[3], - nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + feeScheduleKey: nestedKeyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFeeScheduleKey(response.tokenId, nestedKeyList.key); + verifyTokenCreationWithFeeScheduleKey(response.tokenId, nestedKeyList); }); it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { - const thresholdKey = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -2868,49 +2565,21 @@ describe("TokenCreateTransaction", function () { } ] }); - if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: thresholdKey.key, - commonTransactionParams: { - signers: [ - thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + feeScheduleKey: thresholdKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFeeScheduleKey(response.tokenId, thresholdKey.key); - }); - - it("(#8) Creates a token with a valid key as its fee schedule key but doesn't sign with it", async function () { - const key = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" - }); - if (key.status === "NOT_IMPLEMENTED") this.skip(); - - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: key.key - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); - return; - } - - // The test failed, no error was thrown. - assert.fail("Should throw an error"); + verifyTokenCreationWithFeeScheduleKey(response.tokenId, thresholdKey); }); - it("(#9) Creates a token with an invalid key as its fee schedule key", async function () { + it("(#8) Creates a token with an invalid key as its fee schedule key", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -4052,14 +3721,7 @@ describe("TokenCreateTransaction", function () { it("(#1) Creates a token with a valid ED25519 public key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey", - fromKey: privateKey + type: "ed25519PublicKey" }); const publicKey = response.key; @@ -4067,12 +3729,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + pauseKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -4082,14 +3739,7 @@ describe("TokenCreateTransaction", function () { it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + type: "ecdsaSecp256k1PublicKey" }); const publicKey = response.key; @@ -4097,12 +3747,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + pauseKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -4127,12 +3772,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + pauseKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -4157,12 +3797,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + pauseKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -4171,7 +3806,7 @@ describe("TokenCreateTransaction", function () { }); it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { - const keyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -4185,28 +3820,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: keyList.key, - commonTransactionParams: { - signers: [ - keyList.privateKeys[0], - keyList.privateKeys[1], - keyList.privateKeys[2] - ] - } + pauseKey: keyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithPauseKey(response.tokenId, keyList.key); + verifyTokenCreationWithPauseKey(response.tokenId, keyList); }); it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its pause key", async function () { - const nestedKeyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -4244,31 +3873,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: nestedKeyList.key, - commonTransactionParams: { - signers: [ - nestedKeyList.privateKeys[0], - nestedKeyList.privateKeys[1], - nestedKeyList.privateKeys[2], - nestedKeyList.privateKeys[3], - nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + pauseKey: nestedKeyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithPauseKey(response.tokenId, nestedKeyList.key); + verifyTokenCreationWithPauseKey(response.tokenId, nestedKeyList); }); it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { - const thresholdKey = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -4283,49 +3903,21 @@ describe("TokenCreateTransaction", function () { } ] }); - if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: thresholdKey.key, - commonTransactionParams: { - signers: [ - thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + pauseKey: thresholdKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithPauseKey(response.tokenId, thresholdKey.key); - }); - - it("(#8) Creates a token with a valid key as its pause key but doesn't sign with it", async function () { - const key = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" - }); - if (key.status === "NOT_IMPLEMENTED") this.skip(); - - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: key.key - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); - return; - } - - // The test failed, no error was thrown. - assert.fail("Should throw an error"); + verifyTokenCreationWithPauseKey(response.tokenId, thresholdKey); }); - it("(#9) Creates a token with an invalid key as its pause key", async function () { + it("(#8) Creates a token with an invalid key as its pause key", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -4675,7 +4267,7 @@ describe("TokenCreateTransaction", function () { // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - });*/ + }); return Promise.resolve(); }); From a51a3e2faca49140e95a3acb2e14b8e0d1c02f38 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Wed, 28 Aug 2024 15:50:44 -0500 Subject: [PATCH 06/25] fix: creating a token with freezeDefault=true requires a freeze key Signed-off-by: Rob Walworth --- .../test_tokenCreateTransaction.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index 1be84d5..7bd7592 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -24,7 +24,7 @@ describe("TokenCreateTransaction", function () { afterEach(async function () { await JSONRPCRequest("reset"); }); - +/* describe("Name", function () { async function verifyTokenCreationWithName(tokenId, name) { // If the token was created successfully, the queried token's names should be equal. @@ -1784,7 +1784,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); }); - +*/ describe("Freeze Default", function () { async function verifyTokenCreationWithFreezeDefault(tokenId, freezeDefault) { expect(freezeDefault).to.equal(await consensusInfoClient.getTokenInfo(tokenId).freezeDefault); @@ -1792,11 +1792,18 @@ describe("TokenCreateTransaction", function () { } it("(#1) Creates a token with a frozen default status", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + const freezeDefault = true; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: key, freezeDefault: freezeDefault }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -1806,7 +1813,7 @@ describe("TokenCreateTransaction", function () { it("(#2) Creates a token with an unfrozen default status", async function () { const freezeDefault = false; - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, @@ -1817,7 +1824,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithFreezeDefault(response.tokenId, freezeDefault); }); }); - +/* describe("Expiration Time", function () { it("(#1) Creates a token with a valid expiration time", async function () { const expirationTimeSeconds = (Date.now() / 1000) + 5184000; @@ -4268,6 +4275,6 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); }); - +*/ return Promise.resolve(); }); From b72b95dcedfcd93735ab0be0bdad527074c6538a Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Fri, 30 Aug 2024 13:20:57 -0400 Subject: [PATCH 07/25] fix: get most tests working Signed-off-by: Rob Walworth --- .../test_tokenCreateTransaction.js | 444 ++++++++---------- 1 file changed, 198 insertions(+), 246 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index 7bd7592..6249a76 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -2,7 +2,7 @@ import { JSONRPCRequest } from "../../client.js"; import mirrorNodeClient from "../../mirrorNodeClient.js"; import consensusInfoClient from "../../consensusInfoClient.js"; import { setOperator } from "../../setup_Tests.js"; -import crypto from "crypto"; +import crypto, { verify } from "crypto"; import { assert, expect } from "chai"; // Needed to convert BigInts to JSON number format. @@ -24,7 +24,7 @@ describe("TokenCreateTransaction", function () { afterEach(async function () { await JSONRPCRequest("reset"); }); -/* + describe("Name", function () { async function verifyTokenCreationWithName(tokenId, name) { // If the token was created successfully, the queried token's names should be equal. @@ -1784,7 +1784,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); }); -*/ + describe("Freeze Default", function () { async function verifyTokenCreationWithFreezeDefault(tokenId, freezeDefault) { expect(freezeDefault).to.equal(await consensusInfoClient.getTokenInfo(tokenId).freezeDefault); @@ -1824,10 +1824,10 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithFreezeDefault(response.tokenId, freezeDefault); }); }); -/* + describe("Expiration Time", function () { it("(#1) Creates a token with a valid expiration time", async function () { - const expirationTimeSeconds = (Date.now() / 1000) + 5184000; + const expirationTimeSeconds = parseInt((Date.now() / 1000) + 5184000); const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -1835,9 +1835,10 @@ describe("TokenCreateTransaction", function () { expirationTime: expirationTimeSeconds }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + const tokenId = response.tokenId; - expect(expirationTime).to.equal(await consensusInfoClient.getTokenInfo(tokenId).expirationTime); - expect(expirationTime).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].expiry_timestamp); + expect(expirationTimeSeconds).to.equal(await consensusInfoClient.getTokenInfo(tokenId).expirationTime); + expect(expirationTimeSeconds).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].expiry_timestamp); }); it("(#2) Creates a token with an expiration time of one less than the current time", async function () { @@ -1895,8 +1896,15 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewAccountId: accountId + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [ + key + ] + } }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const tokenId = response.tokenId; expect(accountId).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewAccountId.toString()); expect(accountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_account); @@ -1967,7 +1975,12 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewAccountId: accountId + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [ + key + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1988,7 +2001,7 @@ describe("TokenCreateTransaction", function () { it ("(#1) Creates a token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { const autoRenewPeriod = 5184000 - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, @@ -2018,7 +2031,7 @@ describe("TokenCreateTransaction", function () { it ("(#3) Creates a token with an auto renew period set to the minimum period of 30 days (2,592,000 seconds)", async function () { const autoRenewPeriod = 2592000; - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, @@ -2038,7 +2051,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2048,7 +2061,7 @@ describe("TokenCreateTransaction", function () { it ("(#5) Creates a token with an auto renew period set to the maximum period of 8,000,001 seconds", async function () { const autoRenewPeriod = 8000001; - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, @@ -2068,7 +2081,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2208,7 +2221,8 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - tokenType: "finite" + supplyType: "finite", + maxSupply: 1000000 }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2220,7 +2234,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - tokenType: "infinite" + supplyType: "infinite" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2282,7 +2296,7 @@ describe("TokenCreateTransaction", function () { }); it("(#4) Creates a fungible token with the maximum max supply", async function () { - const maxSupply = 9223372036854775807; + const maxSupply = 9223372036854775807n; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -2302,7 +2316,7 @@ describe("TokenCreateTransaction", function () { symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyType: "finite", - maxSupply: 9223372036854775808 + maxSupply: 9223372036854775808n }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2332,7 +2346,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Creates an NFT with an max supply of zero", async function () { + it("(#7) Creates an NFT with a max supply of zero", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); @@ -2345,7 +2359,7 @@ describe("TokenCreateTransaction", function () { symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: key, - supplyType: "infinite", + supplyType: "finite", tokenType: "nft", maxSupply: 0 }); @@ -2743,7 +2757,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } } @@ -2770,7 +2784,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fractionalFee: { numerator: numerator, denominator: denominator, minimumAmount: minAmount, @@ -2807,7 +2821,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + royaltyFee: { numerator: numerator, denominator: denominator, fallbackFee: { @@ -2830,13 +2844,15 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: { - feeCollectorAccountId: "123.456.789", - feeCollectorsExempt: false, - fee: { - amount: 10 + customFees: [ + { + feeCollectorAccountId: "123.456.789", + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } } - } + ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2854,13 +2870,15 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: { - feeCollectorAccountId: "", - feeCollectorsExempt: false, - fee: { - amount: 10 + customFees: [ + { + feeCollectorAccountId: "", + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } } - } + ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2901,13 +2919,15 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: { - feeCollectorAccountId: accountId, - feeCollectorsExempt: false, - fee: { - amount: 10 + customFees: [ + { + feeCollectorAccountId: accountId, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } } - } + ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2931,7 +2951,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } } @@ -2948,17 +2968,19 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fee: { - amount: 0 + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 0 + } } - } + ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -2969,7 +2991,7 @@ describe("TokenCreateTransaction", function () { it("(#9) Creates a token with a fixed fee with the maximum amount", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; - const amount = parseInt(9223372036854775807); + const amount = 9223372036854775807n; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -2978,7 +3000,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } } @@ -2995,17 +3017,19 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fee: { - amount: 9223372036854775808 + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 9223372036854775808n + } } - } + ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3026,7 +3050,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount, denominatingTokenId: denominatingTokenId } @@ -3044,18 +3068,19 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: { + customFees: [ { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fee: { + fixedFee: { amount: 10, denominatingTokenId: "123.456.789" } } + ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); + assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); return; } @@ -3069,14 +3094,15 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: { + customFees: [ { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fee: { + fixedFee: { amount: 10, denominatingTokenId: "" } } + ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -3107,17 +3133,19 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fee: { - amount: 10, - denominatingTokenId: tokenId + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10, + denominatingTokenId: tokenId + } } - } + ] }); } catch (err) { - assert.equal(err.code.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); + assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); return; } @@ -3129,7 +3157,7 @@ describe("TokenCreateTransaction", function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; - const denominator = parseInt(9223372036854775807); + const denominator = 9223372036854775807n; const minAmount = 1; const maxAmount = 10; const assessmentMethod = "inclusive"; @@ -3141,7 +3169,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fractionalFee: { numerator: numerator, denominator: denominator, minimumAmount: minAmount, @@ -3166,9 +3194,9 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fee: { + fractionalFee: { numerator: 0, - denominator: 9223372036854775807, + denominator: 9223372036854775807n, minimumAmount: 1, maximumAmount: 10, assessmentMethod: "inclusive" @@ -3178,7 +3206,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3189,7 +3217,7 @@ describe("TokenCreateTransaction", function () { it("(#17) Creates a token with a fractional fee with the maximum fractional amount", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; - const numerator = parseInt(9223372036854775807); + const numerator = 9223372036854775807n; const denominator = 1; const minAmount = 1; const maxAmount = 10; @@ -3202,7 +3230,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fractionalFee: { numerator: numerator, denominator: denominator, minimumAmount: minAmount, @@ -3227,8 +3255,8 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fee: { - numerator: parseInt(9223372036854775808), + fractionalFee: { + numerator: 9223372036854775808n, denominator: 1, minimumAmount: 1, maximumAmount: 10, @@ -3239,7 +3267,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3263,7 +3291,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fractionalFee: { numerator: numerator, denominator: denominator, minimumAmount: minAmount, @@ -3288,7 +3316,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fee: { + fractionalFee: { numerator: 1, denominator: 10, minimumAmount: -1, @@ -3300,7 +3328,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3314,7 +3342,7 @@ describe("TokenCreateTransaction", function () { const numerator = 1; const denominator = 10; const minAmount = 1; - const maxAmount = parseInt(9223372036854775807); + const maxAmount = 9223372036854775807n; const assessmentMethod = "inclusive"; const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3324,7 +3352,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fractionalFee: { numerator: numerator, denominator: denominator, minimumAmount: minAmount, @@ -3349,11 +3377,11 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fee: { + fractionalFee: { numerator: 1, denominator: 10, minimumAmount: 1, - maximumAmount: parseInt(9223372036854775808), + maximumAmount: 9223372036854775808n, assessmentMethod: "inclusive" } } @@ -3361,7 +3389,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3379,7 +3407,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fee: { + fractionalFee: { numerator: 1, denominator: 10, minimumAmount: 10, @@ -3391,7 +3419,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); + assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); return; } @@ -3415,7 +3443,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fractionalFee: { numerator: numerator, denominator: denominator, minimumAmount: minAmount, @@ -3440,7 +3468,7 @@ describe("TokenCreateTransaction", function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; - const denominator = parseInt(9223372036854775807); + const denominator = 9223372036854775807n; const fallbackFeeAmount = 10; response = await JSONRPCRequest("createToken", { name: "testname", @@ -3452,7 +3480,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + royaltyFee: { numerator: numerator, denominator: denominator, fallbackFee: { @@ -3487,9 +3515,9 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fee: { + royaltyFee: { numerator: 0, - denominator: parseInt(9223372036854775807), + denominator: 9223372036854775807n, fallbackFee: { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, @@ -3501,7 +3529,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3516,36 +3544,37 @@ describe("TokenCreateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = parseInt(9223372036854775807); - const denominator = 1; - const fallbackFeeAmount = 10; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fee: { - numerator: numerator, - denominator: denominator, - fallbackFee: { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - amount: fallbackFeeAmount + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 9223372036854775807n, + denominator: 1, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } } } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "ROYALTY_FRACTION_CANNOT_EXCEED_ONE"); + return; + } - verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); + // The test failed, no error was thrown. + assert.fail("Should throw an error"); }); it("(#28) Creates a token with a royalty fee with the amount above the maximum fractional amount", async function () { @@ -3566,8 +3595,8 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fee: { - numerator: parseInt(9223372036854775808), + royaltyFee: { + numerator: 9223372036854775808n, denominator: 1, fallbackFee: { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, @@ -3580,7 +3609,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3598,7 +3627,7 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fee: { + royaltyFee: { numerator: 1, denominator: 10, fallbackFee: { @@ -3612,7 +3641,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "CUSTOM_ROYALTY_FEE_ONLY_ALLOWED_FOR_NON_FUNGIBLE_UNIQUE"); + assert.equal(err.data.status, "CUSTOM_ROYALTY_FEE_ONLY_ALLOWED_FOR_NON_FUNGIBLE_UNIQUE"); return; } @@ -3633,77 +3662,77 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } }, { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } }, { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } }, { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } }, { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } }, { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } }, { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } }, { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } }, { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } }, { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } }, { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fee: { + fixedFee: { amount: amount } }, @@ -3711,7 +3740,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code.status, "CUSTOM_FEES_LIST_TOO_LONG"); + assert.equal(err.data.status, "CUSTOM_FEES_LIST_TOO_LONG"); return; } @@ -3984,14 +4013,7 @@ describe("TokenCreateTransaction", function () { it("(#1) Creates a token with a valid ED25519 public key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey", - fromKey: privateKey + type: "ed25519PublicKey" }); const publicKey = response.key; @@ -3999,29 +4021,17 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + metadataKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + type: "ecdsaSecp256k1PublicKey" }); const publicKey = response.key; @@ -4029,17 +4039,12 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: publicKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + metadataKey: publicKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); it("(#3) Creates a token with a valid ED25519 private key as its metadata key", async function () { @@ -4059,17 +4064,12 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + metadataKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its metadata key", async function () { @@ -4089,21 +4089,16 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: privateKey, - commonTransactionParams: { - signers: [ - privateKey - ] - } + metadataKey: privateKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { - const keyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -4117,28 +4112,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: keyList.key, - commonTransactionParams: { - signers: [ - keyList.privateKeys[0], - keyList.privateKeys[1], - keyList.privateKeys[2] - ] - } + metadataKey: keyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithPauseKey(response.tokenId, keyList.key); + verifyTokenCreationWithMetadataKey(response.tokenId, keyList.key); }); it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its metadata key", async function () { - const nestedKeyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -4176,31 +4165,22 @@ describe("TokenCreateTransaction", function () { } ] }); - if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: nestedKeyList.key, - commonTransactionParams: { - signers: [ - nestedKeyList.privateKeys[0], - nestedKeyList.privateKeys[1], - nestedKeyList.privateKeys[2], - nestedKeyList.privateKeys[3], - nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + metadataKey: nestedKeyList }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithPauseKey(response.tokenId, nestedKeyList.key); + verifyTokenCreationWithMetadataKey(response.tokenId, nestedKeyList.key); }); it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { - const thresholdKey = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -4215,49 +4195,21 @@ describe("TokenCreateTransaction", function () { } ] }); - if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: thresholdKey.key, - commonTransactionParams: { - signers: [ - thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + metadataKey: thresholdKey }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithPauseKey(response.tokenId, thresholdKey.key); - }); - - it("(#8) Creates a token with a valid key as its metadata key but doesn't sign with it", async function () { - const key = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" - }); - if (key.status === "NOT_IMPLEMENTED") this.skip(); - - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: key.key - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); - return; - } - - // The test failed, no error was thrown. - assert.fail("Should throw an error"); + verifyTokenCreationWithMetadataKey(response.tokenId, thresholdKey.key); }); - it("(#9) Creates a token with an invalid key as its metadata key", async function () { + it("(#8) Creates a token with an invalid key as its metadata key", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -4275,6 +4227,6 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); }); -*/ + return Promise.resolve(); }); From 386910e72c4779b031677fa5d52fe03268fd4092 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Fri, 30 Aug 2024 17:48:22 -0400 Subject: [PATCH 08/25] fix: align tests with specs Signed-off-by: Rob Walworth --- .../test_tokenCreateTransaction.js | 372 ++++++++++++------ 1 file changed, 246 insertions(+), 126 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index 6249a76..320b08f 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -27,13 +27,11 @@ describe("TokenCreateTransaction", function () { describe("Name", function () { async function verifyTokenCreationWithName(tokenId, name) { - // If the token was created successfully, the queried token's names should be equal. expect(name).to.equal(await consensusInfoClient.getTokenInfo(tokenId).name); expect(name).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].name); } it("(#1) Creates a token with a name that is a valid length", async function () { - // Attempt to create a token with a name that is a valid length. const name = "testname"; const response = await JSONRPCRequest("createToken", { name: name, @@ -42,12 +40,10 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - // Verify the token was created. verifyTokenCreationWithName(response.tokenId, name); }); it("(#2) Creates a token with a name that is the minimum length", async function () { - // Attempt to create a token with a name that is the minimum length. const name = "t"; const response = await JSONRPCRequest("createToken", { name: name, @@ -56,13 +52,11 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - // Verify the token was created. verifyTokenCreationWithName(response.tokenId, name); }); it("(#3) Creates a token with a name that is empty", async function () { try { - // Attempt to create a token with a name that is empty. The network should respond with a MISSING_TOKEN_NAME status. const response = await JSONRPCRequest("createToken", { name: "", symbol: "testsymbol", @@ -74,12 +68,10 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); it("(#4) Creates a token with a name that is the maximum length", async function () { - // Attempt to create a token with a name that is the maximum length. const name = "This is a really long name but it is still valid because it is 100 characters exactly on the money!!" const response = await JSONRPCRequest("createToken", { name: name, @@ -88,13 +80,11 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - // Verify the token was created. verifyTokenCreationWithName(response.tokenId, name); }); it("(#5) Creates a token with a name that exceeds the maximum length", async function () { try { - // Attempt to create a token with a name that exceeds the maximum length. The network should respond with a TOKEN_NAME_TOO_LONG status. const response = await JSONRPCRequest("createToken", { name: "This is a long name that is not valid because it exceeds 100 characters and it should fail the test!!", symbol: "testsymbol", @@ -106,13 +96,11 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); it("(#6) Creates a token with no name", async function () { try { - // Attempt to create a token with no name. The network should respond with a MISSING_TOKEN_NAME status. const response = await JSONRPCRequest("createToken", { symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID @@ -123,20 +111,17 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); describe("Symbol", function () { async function verifyTokenCreationWithSymbol(tokenId, symbol) { - // If the token was created successfully, the queried token's symbols should be equal. expect(symbol).to.equal(await consensusInfoClient.getTokenInfo(tokenId).symbol); expect(symbol).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].symbol); } it("(#1) Creates a token with a symbol that is the minimum length", async function () { - // Attempt to create a token with a symbol that is the minimum length. const symbol = "t"; const response = await JSONRPCRequest("createToken", { name: "testname", @@ -145,13 +130,11 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - // Verify the token was created. verifyTokenCreationWithSymbol(response.tokenId, symbol); }); it("(#2) Creates a token with a symbol that is empty", async function () { try { - // Attempt to create a token with a symbol that is empty. The network should respond with a MISSING_TOKEN_SYMBOL status. const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "", @@ -163,12 +146,10 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); it("(#3) Creates a token with a symbol that is the maximum length", async function () { - // Attempt to create a token with a symbol that is the maximum length. const symbol = "This is a really long symbol but it is still valid because it is 100 characters exactly on the money"; const response = await JSONRPCRequest("createToken", { name: "testname", @@ -177,13 +158,11 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - // Verify the token was created. verifyTokenCreationWithSymbol(response.tokenId, symbol); }); it("(#4) Creates a token with a symbol that exceeds the maximum length", async function () { try { - // Attempt to create a token with a symbol that exceeds the maximum length. The network should respond with a TOKEN_SYMBOL_TOO_LONG status. const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "This is a long symbol that is not valid because it exceeds 100 characters and it should fail the test", @@ -195,13 +174,11 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); it("(#5) Creates a token with no symbol", async function () { try { - // Attempt to create a token with no symbol. The network should respond with a MISSING_TOKEN_SYMBOL status. const response = await JSONRPCRequest("createToken", { name: "testname", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID @@ -212,20 +189,17 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); describe("Decimals", function () { async function verifyTokenCreationWithDecimals(tokenId, decimals) { - // If the token was created successfully, the queried token's decimals should be equal. expect(decimals).to.equal(await consensusInfoClient.getTokenInfo(tokenId).decimals); expect(decimals).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].decimals); } it("(#1) Creates a fungible token with a valid amount of decimals", async function () { - // Attempt to create a token with a valid amount of decimals. const decimals = 3; const response = await JSONRPCRequest("createToken", { name: "testname", @@ -235,12 +209,10 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - // Verify the token was created. verifyTokenCreationWithDecimals(response.tokenId, decimals); }); it("(#2) Creates a fungible token with the minimum amount of decimals", async function () { - // Attempt to create a token with the minimum amount of decimals. const decimals = 0; const response = await JSONRPCRequest("createToken", { name: "testname", @@ -250,13 +222,11 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - // Verify the token was created. verifyTokenCreationWithDecimals(response.tokenId, decimals); }); it("(#3) Creates a fungible token with a decimal amount below the minimum amount", async function () { try { - // Attempt to create a token with a decimal amount below the minimum amount. The network should respond with a INVALID_TOKEN_DECIMALS status. const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -269,12 +239,10 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); it("(#4) Creates a fungible token with the maximum amount of decimals", async function () { - // Attempt to create a token with the maximum amount of decimals. const decimals = 2147483647; const response = await JSONRPCRequest("createToken", { name: "testname", @@ -284,13 +252,11 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - // Verify the token was created. verifyTokenCreationWithDecimals(response.tokenId, decimals); }); it("(#5) Creates a fungible token with a decimal amount that exceeds the maximum amount", async function () { try { - // Attempt to create a token with a decimal amount that exceeds the maximum amount. The network should respond with a INVALID_TOKEN_DECIMALS status. const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -303,33 +269,32 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); it("(#6) Creates an NFT with a decimal amount of zero", async function () { - try { - // Attempt to create an NFT with a decimal amount of zero. The network should respond with a TOKEN_HAS_NO_SUPPLY_KEY status. - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: 0, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - tokenType: "nft" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); - return; - } + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; - // The test failed, no error was thrown. - assert.fail("Should throw an error"); + const decimals = 0; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithDecimals(response.tokenId, decimals); }); it("(#7) Creates an NFT with a nonzero decimal amount", async function () { try { - // Attempt to create an NFT with a nonzero decimal amount. The network should respond with a INVALID_TOKEN_DECIMALS status. const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -367,7 +332,37 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); }); - it("(#2) Creates a fungible token with the minimum initial supply", async function () { + it("(#2) Creates a fungible token with a valid initial supply and decimals", async function () { + const decimals = 2; + const initialSupply = 1000000; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + initialSupply: initialSupply, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply / (10 ** decimals)); + }); + + it("(#3) Creates a fungible token with a valid initial supply and more decimals", async function () { + const decimals = 6; + const initialSupply = 1000000; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + initialSupply: initialSupply, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply / (10 ** decimals)); + }); + + it("(#4) Creates a fungible token with the minimum initial supply", async function () { const initialSupply = 0; const response = await JSONRPCRequest("createToken", { name: "testname", @@ -380,7 +375,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); }); - it("(#3) Creates a fungible token with an initial supply below the minimum amount", async function () { + it("(#5) Creates a fungible token with an initial supply below the minimum amount", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -398,8 +393,8 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Creates a fungible token with the maximum initial supply", async function () { - const initialSupply = 9223372036854775807n; // Workaround for javascript not allowing numbers over 2^53 - 1. + it("(#6) Creates a fungible token with the maximum initial supply", async function () { + const initialSupply = 9223372036854775807n; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -411,7 +406,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); }); - it("(#5) Creates a fungible token with an initial supply that exceeds the maximum amount", async function () { + it("(#7) Creates a fungible token with an initial supply that exceeds the maximum amount", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -429,7 +424,28 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Creates an NFT with an initial supply of zero", async function () { + it("(#8) Creates an NFT with an initial supply of zero", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const initialSupply = 0; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: initialSupply, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); + }); + + it("(#9) Creates an NFT with an initial supply of zero without a supply key", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -448,7 +464,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Creates an NFT with a nonzero initial supply", async function () { + it("(#10) Creates an NFT with a nonzero initial supply", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -570,6 +586,7 @@ describe("TokenCreateTransaction", function () { ] } }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); try { response = await JSONRPCRequest("createToken", { @@ -731,6 +748,9 @@ describe("TokenCreateTransaction", function () { }, { type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" } ] }); @@ -745,7 +765,8 @@ describe("TokenCreateTransaction", function () { signers: [ keyList.privateKeys[0], keyList.privateKeys[1], - keyList.privateKeys[2] + keyList.privateKeys[2], + keyList.privateKeys[3] ] } }); @@ -852,17 +873,18 @@ describe("TokenCreateTransaction", function () { }); it("(#8) Creates a token with a valid key as its admin key but doesn't sign with it", async function () { - const key = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); - if (key.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; try { - const response = await JSONRPCRequest("createToken", { + response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - adminKey: key.key + adminKey: key }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -870,7 +892,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -888,7 +909,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -997,6 +1017,9 @@ describe("TokenCreateTransaction", function () { }, { type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" } ] }); @@ -1220,6 +1243,9 @@ describe("TokenCreateTransaction", function () { }, { type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" } ] }); @@ -1334,7 +1360,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -1443,6 +1468,9 @@ describe("TokenCreateTransaction", function () { }, { type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" } ] }); @@ -1557,7 +1585,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -1666,6 +1693,9 @@ describe("TokenCreateTransaction", function () { }, { type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" } ] }); @@ -1780,7 +1810,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -1811,7 +1840,24 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithFreezeDefault(response.tokenId, freezeDefault); }); - it("(#2) Creates a token with an unfrozen default status", async function () { + it("(#2) Creates a token with a frozen default status and no freeze key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeDefault: true + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_FREEZE_KEY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a token with an unfrozen default status", async function () { const freezeDefault = false; const response = await JSONRPCRequest("createToken", { name: "testname", @@ -1855,7 +1901,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -1865,7 +1910,7 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: (Date.now() / 1000) - 8000002 + expirationTime: (Date.now() / 1000) + 8000002 }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1873,7 +1918,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -1910,7 +1954,36 @@ describe("TokenCreateTransaction", function () { expect(accountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_account); }); - it ("(#2) Creates a token with an auto renew account that doesn't exist", async function () { + it ("(#2) Creates a token with an auto renew account without signing with the account's key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccountId: accountId + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it ("(#3) Creates a token with an auto renew account that doesn't exist", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -1924,11 +1997,10 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it ("(#3) Creates a token with an empty auto renew account", async function () { + it ("(#4) Creates a token with an empty auto renew account", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -1946,7 +2018,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it ("(#4) Creates a token with an auto renew account that is deleted", async function () { + it ("(#5) Creates a token with an auto renew account that is deleted", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -2025,7 +2097,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -2055,7 +2126,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -2085,7 +2155,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -2149,7 +2218,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -2205,7 +2273,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -2291,7 +2358,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -2324,7 +2390,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -2342,7 +2407,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -2369,7 +2433,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -2500,6 +2563,9 @@ describe("TokenCreateTransaction", function () { }, { type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" } ] }); @@ -2614,7 +2680,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -2860,7 +2925,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -2886,7 +2950,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -2935,7 +2998,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -2984,7 +3046,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -3033,7 +3094,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -3084,7 +3144,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -3094,14 +3153,15 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10, - denominatingTokenId: "" + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10, + denominatingTokenId: "" + } } - } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -3110,7 +3170,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -3149,7 +3208,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -3210,7 +3268,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); @@ -3271,11 +3328,39 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it("(#19) Creates a token with a fractional fee with the minimum minimum amount", async function () { + it("(#19) Creates a token with a fractional fee with a 0 denominator", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 0, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "FRACTION_DIVIDES_BY_ZERO"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#20) Creates a token with a fractional fee with the minimum minimum amount", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; @@ -3306,7 +3391,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); }); - it("(#20) Creates a token with a fractional fee with the minimum amount below the minimum amount", async function () { + it("(#21) Creates a token with a fractional fee with the minimum amount below the minimum amount", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3332,11 +3417,10 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it("(#21) Creates a token with a fractional fee with the maximum maximum amount", async function () { + it("(#22) Creates a token with a fractional fee with the maximum maximum amount", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; @@ -3367,7 +3451,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); }); - it("(#22) Creates a token with a fractional fee with the maximum amount above the maximum amount", async function () { + it("(#23) Creates a token with a fractional fee with the maximum amount above the maximum amount", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3393,11 +3477,10 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it("(#23) Creates a token with a fractional fee with the minimum amount higher than the maximum amount", async function () { + it("(#24) Creates a token with a fractional fee with the minimum amount higher than the maximum amount", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3423,11 +3506,10 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it("(#24) Creates a token with a fractional fee that is assessed to the receiver", async function () { + it("(#25) Creates a token with a fractional fee that is assessed to the receiver", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; @@ -3458,7 +3540,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); }); - it("(#25) Creates a token with a royalty fee with the minimum fractional amount", async function () { + it("(#26) Creates a token with a royalty fee with the minimum fractional amount", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }) @@ -3497,7 +3579,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); }); - it("(#26) Creates a token with a royalty fee with the amount below the minimum fractional amount", async function () { + it("(#27) Creates a token with a royalty fee with the amount below the minimum fractional amount", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -3533,11 +3615,10 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it("(#27) Creates a token with a royalty fee with the maximum fractional amount", async function () { + it("(#28) Creates a token with a royalty fee with the maximum fractional amount", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }) @@ -3573,11 +3654,10 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it("(#28) Creates a token with a royalty fee with the amount above the maximum fractional amount", async function () { + it("(#29) Creates a token with a royalty fee with the amount above the maximum fractional amount", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -3613,11 +3693,49 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it("(#29) Creates a fungible token with a royalty fee", async function () { + it("(#30) Creates a token with a royalty fee with a 0 denominator", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 0, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "FRACTION_DIVIDES_BY_ZERO"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#31) Creates a fungible token with a royalty fee", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3645,11 +3763,10 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it("(#30) Creates a token with more than the maximum amount of fees allowed", async function () { + it("(#32) Creates a token with more than the maximum amount of fees allowed", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const amount = 10; @@ -3744,7 +3861,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -3853,6 +3969,9 @@ describe("TokenCreateTransaction", function () { }, { type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" } ] }); @@ -3967,7 +4086,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -4109,6 +4227,9 @@ describe("TokenCreateTransaction", function () { }, { type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" } ] }); @@ -4223,7 +4344,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); From d0fabaad5f26528df3d53fe1424eb5536cf7be81 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Tue, 3 Sep 2024 14:15:39 -0400 Subject: [PATCH 09/25] feat: add new decimals tests Signed-off-by: Rob Walworth --- .../test_tokenCreateTransaction.js | 107 ++++++++++++++---- 1 file changed, 87 insertions(+), 20 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index 320b08f..faf85b0 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -199,20 +199,7 @@ describe("TokenCreateTransaction", function () { expect(decimals).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].decimals); } - it("(#1) Creates a fungible token with a valid amount of decimals", async function () { - const decimals = 3; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: decimals, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithDecimals(response.tokenId, decimals); - }); - - it("(#2) Creates a fungible token with the minimum amount of decimals", async function () { + it("(#1) Creates a fungible token with 0 decimals", async function () { const decimals = 0; const response = await JSONRPCRequest("createToken", { name: "testname", @@ -225,7 +212,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithDecimals(response.tokenId, decimals); }); - it("(#3) Creates a fungible token with a decimal amount below the minimum amount", async function () { + it("(#2) Creates a fungible token with -1 decimals", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -242,7 +229,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Creates a fungible token with the maximum amount of decimals", async function () { + it("(#3) Creates a fungible token with 2,147,483,647 (int32 max) decimals", async function () { const decimals = 2147483647; const response = await JSONRPCRequest("createToken", { name: "testname", @@ -255,7 +242,20 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithDecimals(response.tokenId, decimals); }); - it("(#5) Creates a fungible token with a decimal amount that exceeds the maximum amount", async function () { + it("(#4) Creates a fungible token with 2,147,483,646 (int32 max - 1) decimals", async function () { + const decimals = 2147483646; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithDecimals(response.tokenId, decimals); + }); + + it("(#5) Creates a fungible token with 2,147,483,648 (int32 max + 1) decimals", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -272,7 +272,75 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Creates an NFT with a decimal amount of zero", async function () { + it("(#6) Creates a fungible token with 4,294,967,295 (uint32 max) decimals", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: 4294967295, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#7) Creates a fungible token with 4,294,967,294 (uint32 max - 1) decimals", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: 4294967294, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#8) Creates a fungible token with -2,147,483,648 (int32 min) decimals", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: -2147483648, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a fungible token with -2,147,483,647 (int32 min + 1) decimals", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: -2147483647, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#10) Creates an NFT with a decimal amount of zero", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); @@ -293,7 +361,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithDecimals(response.tokenId, decimals); }); - it("(#7) Creates an NFT with a nonzero decimal amount", async function () { + it("(#11) Creates an NFT with a nonzero decimal amount", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -308,7 +376,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); From 5b788f1149c54bc5ac6b76ae1c3f511098c9e49b Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Tue, 3 Sep 2024 15:15:59 -0400 Subject: [PATCH 10/25] feat: add additional int tests Signed-off-by: Rob Walworth --- .../test_tokenCreateTransaction.js | 491 ++++++++++++++---- 1 file changed, 383 insertions(+), 108 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index faf85b0..2f76c8f 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -386,8 +386,8 @@ describe("TokenCreateTransaction", function () { expect(initialSupply).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].initial_supply); } - it("(#1) Creates a fungible token with a valid initial supply", async function () { - const initialSupply = 1000000; + it("(#1) Creates a fungible token with 0 initial supply", async function () { + const initialSupply = 0; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -399,38 +399,38 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); }); - it("(#2) Creates a fungible token with a valid initial supply and decimals", async function () { - const decimals = 2; - const initialSupply = 1000000; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: decimals, - initialSupply: initialSupply, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + it("(#2) Creates a fungible token with -1 initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: -1, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } - verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply / (10 ** decimals)); + assert.fail("Should throw an error"); }); - it("(#3) Creates a fungible token with a valid initial supply and more decimals", async function () { - const decimals = 6; - const initialSupply = 1000000; + it("(#3) Creates a fungible token with 9,223,372,036,854,775,807 (int64 max) initial supply", async function () { + const initialSupply = 9223372036854775807n; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - decimals: decimals, initialSupply: initialSupply, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply / (10 ** decimals)); + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); }); - it("(#4) Creates a fungible token with the minimum initial supply", async function () { - const initialSupply = 0; + it("(#4) Creates a fungible token with 9,223,372,036,854,775,806 (int64 max - 1) initial supply", async function () { + const initialSupply = 9223372036854775806n; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -442,12 +442,12 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); }); - it("(#5) Creates a fungible token with an initial supply below the minimum amount", async function () { + it("(#5) Creates a fungible token with 9,223,372,036,854,775,808 (int64 max + 1) initial supply", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - initialSupply: -1, + initialSupply: 9223372036854775808n, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -456,29 +456,32 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it("(#6) Creates a fungible token with the maximum initial supply", async function () { - const initialSupply = 9223372036854775807n; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: initialSupply, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + it("(#6) Creates a fungible token with 18,446,744,073,709,551,615 (uint64 max) initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: 18446744073709551615n, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } - verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); + assert.fail("Should throw an error"); }); - it("(#7) Creates a fungible token with an initial supply that exceeds the maximum amount", async function () { + it("(#7) Creates a fungible token with 18,446,744,073,709,551,614 (uint64 max - 1) initial supply", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", - initialSupply: 9223372036854775808n, + initialSupply: 18446744073709551614n, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -487,11 +490,74 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it("(#8) Creates an NFT with an initial supply of zero", async function () { + it("(#8) Creates a fungible token with -9,223,372,036,854,775,808 (int64 min) initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: -9223372036854775808n, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a fungible token with -9,223,372,036,854,775,807 (int64 min + 1) initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: -9223372036854775807n, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#10) Creates a fungible token with a valid initial supply and decimals", async function () { + const decimals = 2; + const initialSupply = 1000000; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + initialSupply: initialSupply, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply / (10 ** decimals)); + }); + + it("(#11) Creates a fungible token with a valid initial supply and more decimals", async function () { + const decimals = 6; + const initialSupply = 1000000; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + initialSupply: initialSupply, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply / (10 ** decimals)); + }); + + it("(#12) Creates an NFT with an initial supply of zero", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -512,7 +578,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); }); - it("(#9) Creates an NFT with an initial supply of zero without a supply key", async function () { + it("(#13) Creates an NFT with an initial supply of zero without a supply key", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -527,11 +593,10 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); - it("(#10) Creates an NFT with a nonzero initial supply", async function () { + it("(#14) Creates an NFT with a nonzero initial supply", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -546,7 +611,6 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); @@ -1939,28 +2003,35 @@ describe("TokenCreateTransaction", function () { }); describe("Expiration Time", function () { - it("(#1) Creates a token with a valid expiration time", async function () { - const expirationTimeSeconds = parseInt((Date.now() / 1000) + 5184000); - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: expirationTimeSeconds - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const tokenId = response.tokenId; + async function verifyTokenCreationWithExpirationTime(tokenId, expirationTime) { + expect(expirationTime).to.equal(await consensusInfoClient.getTokenInfo(tokenId).expirationTime); + expect(expirationTime).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].expiry_timestamp); + } - expect(expirationTimeSeconds).to.equal(await consensusInfoClient.getTokenInfo(tokenId).expirationTime); - expect(expirationTimeSeconds).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].expiry_timestamp); + it("(#1) Creates a token with an expiration time of 0 seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 0 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); }); - it("(#2) Creates a token with an expiration time of one less than the current time", async function () { + it("(#2) Creates a token with an expiration time of -1 seconds", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: (Date.now() / 1000) - 1 + expirationTime: -1 }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1971,7 +2042,182 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Creates a token with an expiration time 8,000,002 seconds from the current time", async function () { + it("(#3) Creates a token with an expiration time of 9,223,372,036,854,775,807 (int64 max) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 9223372036854775807n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#4) Creates a token with an expiration time of 9,223,372,036,854,775,806 (int64 max - 1) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 9223372036854775806n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#5) Creates a token with an expiration time of 9,223,372,036,854,775,808 (int64 max + 1) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 9223372036854775808n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#6) Creates a token with an expiration time of 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 18446744073709551615n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#7) Creates a token with an expiration time of 18,446,744,073,709,551,614 (uint64 max - 1) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 18446744073709551614n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#8) Creates a token with an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: -9223372036854775808n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: -9223372036854775807n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#10) Creates a token with an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { + const expirationTime = parseInt((Date.now() / 1000) + 5184000); + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: expirationTime + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithExpirationTime(response.tokenId, expirationTime); + }); + + it("(#11) Creates a token with an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { + const expirationTime = parseInt((Date.now() / 1000) + 2592000); + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: expirationTime + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithExpirationTime(response.tokenId, expirationTime); + }); + + //it("(#12) Creates a token with an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { + // try { + // const response = await JSONRPCRequest("createToken", { + // name: "testname", + // symbol: "testsymbol", + // treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + // expirationTime: (Date.now() / 1000) + 2591999 + // }); + // if (response.status === "NOT_IMPLEMENTED") this.skip(); + // } catch (err) { + // assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + // return; + // } + // + // assert.fail("Should throw an error"); + //}); + + it("(#13) Creates a token with an expiration time of 8,000,001 seconds from the current time", async function () { + const expirationTime = parseInt((Date.now() / 1000) + 8000001); + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: expirationTime + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithExpirationTime(response.tokenId, expirationTime); + }); + + it("(#14) Creates a token with an expiration time of 8,000,002 seconds from the current time", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -2382,8 +2628,44 @@ describe("TokenCreateTransaction", function () { expect(maxSupply).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].max_supply); } - it("(#1) Creates a fungible token with a valid max supply", async function () { - const maxSupply = 1000000; + it("(#1) Creates a token with 0 max supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: 0 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Creates a token with -1 max supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: -1 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a token with 9,223,372,036,854,775,807 (int64 max) max supply", async function () { + const maxSupply = 9223372036854775807n; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -2396,8 +2678,8 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); }); - it("(#2) Creates a fungible token with the minimum max supply", async function () { - const maxSupply = 1; + it("(#4) Creates a token with 9,223,372,036,854,775,806 (int64 max - 1) max supply", async function () { + const maxSupply = 9223372036854775806n; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -2410,14 +2692,14 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); }); - it("(#3) Creates a fungible token with a max supply below the minimum amount", async function () { + it("(#5) Creates a token with 9,223,372,036,854,775,808 (int64 max + 1) max supply", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyType: "finite", - maxSupply: 0 + maxSupply: 9223372036854775808n }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2428,28 +2710,32 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Creates a fungible token with the maximum max supply", async function () { - const maxSupply = 9223372036854775807n; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "finite", - maxSupply: maxSupply - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + it("(#6) Creates a token with 18,446,744,073,709,551,615 (uint64 max) max supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: 18446744073709551615n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } - verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); + assert.fail("Should throw an error"); }); - it("(#5) Creates a fungible token with a max supply that exceeds the maximum amount", async function () { + it("(#7) Creates a token with 18,446,744,073,709,551,614 (uint64 max) max supply", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyType: "finite", - maxSupply: 9223372036854775808n + maxSupply: 18446744073709551614n }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2460,13 +2746,14 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Creates a fungible token with a max supply and an infinite supply type", async function () { + it("(#8) Creates a token with -9,223,372,036,854,775,808 (int64 min) max supply", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - maxSupply: 1000000 + supplyType: "finite", + maxSupply: -9223372036854775808n }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2477,22 +2764,14 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Creates an NFT with a max supply of zero", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - + it("(#9) Creates a token with -9,223,372,036,854,775,807 (int64 min) max supply", async function () { try { - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, supplyType: "finite", - tokenType: "nft", - maxSupply: 0 + maxSupply: -9223372036854775807n }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2503,26 +2782,22 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#8) Creates an NFT with a nonzero max supply", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - const maxSupply = 1000000; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - supplyType: "finite", - tokenType: "nft", - maxSupply: maxSupply - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + it("(#10) Creates a token with a max supply and an infinite supply type", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "infinite", + maxSupply: 1000000 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } - verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); + assert.fail("Should throw an error"); }); }); From 51e92eff2e651de90b78230b3120b71a51f0fab6 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Wed, 4 Sep 2024 16:20:16 -0400 Subject: [PATCH 11/25] fix: add new custom fees tests Signed-off-by: Rob Walworth --- .../test_tokenCreateTransaction.js | 2983 ++++++++++++++--- 1 file changed, 2515 insertions(+), 468 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index 2f76c8f..df4ee70 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -3152,37 +3152,60 @@ describe("TokenCreateTransaction", function () { expect(foundMirrorNodeFee).to.be.true; } - it("(#1) Creates a token with a fixed fee", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const amount = 10; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fixedFee: { - amount: amount + it("(#1) Creates a token with a fixed fee with an amount of 0", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 0 + } } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } - verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); + assert.fail("Should throw an error"); + }); + + it("(#2) Creates a token with a fixed fee with an amount of -1", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: -1 + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); }); - it("(#2) Creates a token with a fractional fee", async function () { + it("(#3) Creates a token with a fixed fee with an amount of 9,223,372,036,854,775,807 (int64 max)", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const minAmount = 1; - const maxAmount = 10; - const assessmentMethod = "inclusive"; + const amount = 9223372036854775807n; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -3191,61 +3214,41 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minAmount, - maximumAmount: maxAmount, - assessmentMethod: assessmentMethod + fixedFee: { + amount: amount } } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); }); - it("(#3) Creates a token with a royalty fee", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - + it("(#4) Creates a token with a fixed fee with an amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const amount = 10; - response = await JSONRPCRequest("createToken", { + const amount = 9223372036854775806n; + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", customFees: [ { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - royaltyFee: { - numerator: numerator, - denominator: denominator, - fallbackFee: { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - amount: amount - } + fixedFee: { + amount: amount } } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, amount); + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); }); - it("(#4) Creates a token with a fee that has a fee collector account that doesn't exist", async function () { + it("(#5) Creates a token with a fixed fee with an amount of 9,223,372,036,854,775,8068 (int64 max + 1)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3253,24 +3256,24 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccountId: "123.456.789", + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fixedFee: { - amount: 10 + amount: 9223372036854775808n } } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } assert.fail("Should throw an error"); }); - it("(#5) Creates a token with a fee with an empty fee collector account", async function () { + it("(#6) Creates a token with a fixed fee with an amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3278,95 +3281,49 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccountId: "", + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fixedFee: { - amount: 10 + amount: 18446744073709551615n } } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code, -32603, "Internal error"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } assert.fail("Should throw an error"); }); - it("(#6) Creates a token with a fee that has a deleted fee collector account", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - response = await JSONRPCRequest("createAccount", { - key: key - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const accountId = response.accountId; - - response = await JSONRPCRequest("deleteAccount", { - deleteAccountId: accountId, - transferAccountId: process.env.OPERATOR_ACCOUNT_ID, - commonTransactionParams: { - signers: [ - key - ] - } - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - + it("(#7) Creates a token with a fixed fee with an amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { try { - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccountId: accountId, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fixedFee: { - amount: 10 + amount: 18446744073709551614n } } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "ACCOUNT_DELETED"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } assert.fail("Should throw an error"); }); - it("(#7) Creates a token with a fixed fee with the minimum amount", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const amount = 1; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fixedFee: { - amount: amount - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); - }); - - it("(#8) Creates a token with a fixed fee with the amount below the minimum amount", async function () { + it("(#8) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,808 (int64 min)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3377,7 +3334,7 @@ describe("TokenCreateTransaction", function () { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fixedFee: { - amount: 0 + amount: -9223372036854775808n } } ] @@ -3391,30 +3348,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#9) Creates a token with a fixed fee with the maximum amount", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const amount = 9223372036854775807n; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fixedFee: { - amount: amount - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); - }); - - it("(#10) Creates a token with a fixed fee with the amount above the maximum amount", async function () { + it("(#9) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3425,7 +3359,7 @@ describe("TokenCreateTransaction", function () { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fixedFee: { - amount: 9223372036854775808n + amount: -9223372036854775807n } } ] @@ -3439,57 +3373,36 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) Creates a token with a fixed fee that is assessed with the created token", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const amount = 10; - const denominatingTokenId = "0.0.0"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fixedFee: { - amount: amount, - denominatingTokenId: denominatingTokenId - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); - }); - - it("(#12) Creates a token with a fixed fee that is assessed with a token that doesn't exist", async function () { + it("(#10) Creates a token with a fractional fee with a numerator of 0", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10, - denominatingTokenId: "123.456.789" + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 0, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } } - } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } assert.fail("Should throw an error"); }); - it("(#13) Creates a token with a fixed fee that is assessed with an empty token", async function () { + it("(#11) Creates a token with a fractional fee with a numerator of -1", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3499,38 +3412,28 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fixedFee: { - amount: 10, - denominatingTokenId: "" + fractionalFee: { + numerator: -1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" } } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code, -32603, "Internal error"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } assert.fail("Should throw an error"); }); - it("(#14) Creates a token with a fixed fee that is assessed with a deleted token", async function () { - let response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const tokenId = response.tokenId; - - response = await JSONRPCRequest("deleteToken", { - tokenId: tokenId - }) - if (response.status === "NOT_IMPLEMENTED") this.skip(); - + it("(#12) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,807 (int64 max)", async function () { try { - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, @@ -3538,53 +3441,55 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fixedFee: { - amount: 10, - denominatingTokenId: tokenId + fractionalFee: { + numerator: 9223372036854775807n, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" } } ] }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } assert.fail("Should throw an error"); }); - it("(#15) Creates a token with a fractional fee with the minimum fractional amount", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 9223372036854775807n; - const minAmount = 1; - const maxAmount = 10; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minAmount, - maximumAmount: maxAmount, - assessmentMethod: assessmentMethod + it("(#13) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 9223372036854775806n, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + assert.fail("Should throw an error"); }); - it("(#16) Creates a token with a fractional fee with the amount below the minimum fractional amount", async function () { + it("(#14) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3595,8 +3500,8 @@ describe("TokenCreateTransaction", function () { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fractionalFee: { - numerator: 0, - denominator: 9223372036854775807n, + numerator: 9223372036854775808n, + denominator: 10, minimumAmount: 1, maximumAmount: 10, assessmentMethod: "inclusive" @@ -3613,38 +3518,36 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#17) Creates a token with a fractional fee with the maximum fractional amount", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 9223372036854775807n; - const denominator = 1; - const minAmount = 1; - const maxAmount = 10; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minAmount, - maximumAmount: maxAmount, - assessmentMethod: assessmentMethod + it("(#15) Creates a token with a fractional fee with a numerator of 18,446,744,073,709,551,615 (uint64 max)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 18446744073709551615n, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + assert.fail("Should throw an error"); }); - it("(#18) Creates a token with a fractional fee with the amount above the maximum fractional amount", async function () { + it("(#16) Creates a token with a fractional fee with a numerator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3655,8 +3558,66 @@ describe("TokenCreateTransaction", function () { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, fractionalFee: { - numerator: 9223372036854775808n, - denominator: 1, + numerator: 18446744073709551614n, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#17) Creates a token with a fractional fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: -9223372036854775808n, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#18) Creates a token with a fractional fee with a numerator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: -9223372036854775807n, + denominator: 10, minimumAmount: 1, maximumAmount: 10, assessmentMethod: "inclusive" @@ -3673,7 +3634,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#19) Creates a token with a fractional fee with a 0 denominator", async function () { + it("(#19) Creates a token with a fractional fee with a denominator of 0", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3702,13 +3663,73 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#20) Creates a token with a fractional fee with the minimum minimum amount", async function () { + it("(#20) Creates a token with a fractional fee with a denominator of -1", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: -1, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#21) Creates a token with a fractional fee with a denominator of 9,223,372,036,854,775,807 (int64 max)", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; - const denominator = 10; - const minAmount = 0; - const maxAmount = 10; + const denominator = 9223372036854775807n; + const minimumAmount = 1; + const maximumAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#22) Creates a token with a fractional fee with a denominator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 9223372036854775806n; + const minimumAmount = 1; + const maximumAmount = 10; const assessmentMethod = "inclusive"; const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3721,8 +3742,8 @@ describe("TokenCreateTransaction", function () { fractionalFee: { numerator: numerator, denominator: denominator, - minimumAmount: minAmount, - maximumAmount: maxAmount, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, assessmentMethod: assessmentMethod } } @@ -3730,10 +3751,10 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); }); - it("(#21) Creates a token with a fractional fee with the minimum amount below the minimum amount", async function () { + it("(#23) Creates a token with a fractional fee with a denominator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3745,8 +3766,8 @@ describe("TokenCreateTransaction", function () { feeCollectorsExempt: false, fractionalFee: { numerator: 1, - denominator: 10, - minimumAmount: -1, + denominator: 9223372036854775808n, + minimumAmount: 1, maximumAmount: 10, assessmentMethod: "inclusive" } @@ -3762,38 +3783,36 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#22) Creates a token with a fractional fee with the maximum maximum amount", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const minAmount = 1; - const maxAmount = 9223372036854775807n; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minAmount, - maximumAmount: maxAmount, - assessmentMethod: assessmentMethod + it("(#24) Creates a token with a fractional fee with a denominator of 18,446,744,073,709,551,615 (uint64 max)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 18446744073709551615n, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); + assert.fail("Should throw an error"); }); - it("(#23) Creates a token with a fractional fee with the maximum amount above the maximum amount", async function () { + it("(#25) Creates a token with a fractional fee with a denominator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -3805,26 +3824,2093 @@ describe("TokenCreateTransaction", function () { feeCollectorsExempt: false, fractionalFee: { numerator: 1, - denominator: 10, + denominator: 18446744073709551614n, minimumAmount: 1, - maximumAmount: 9223372036854775808n, + maximumAmount: 10, assessmentMethod: "inclusive" } } - ] + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#26) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: -9223372036854775808n, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#27) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: -9223372036854775807n, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#28) Creates a token with a fractional fee with a minimum amount of 0", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 0; + const maximumAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#29) Creates a token with a fractional fee with a minimum amount of -1", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: -1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#30) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,807 (int64 max)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 9223372036854775807n; + const maximumAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#31) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 9223372036854775806n; + const maximumAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#32) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 9223372036854775808n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#33) Creates a token with a fractional fee with a minimum amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 18446744073709551615n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#34) Creates a token with a fractional fee with a minimum amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 18446744073709551614n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#35) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: -9223372036854775808n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#36) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: -9223372036854775807n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#37) Creates a token with a fractional fee with a maximum amount of 0", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 0, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#38) Creates a token with a fractional fee with a maximum amount of -1", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: -1, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#39) Creates a token with a fractional fee with a maximum amount of 9,223,372,036,854,775,807 (int64 max)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 9223372036854775807n; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#40) Creates a token with a fractional fee with a maximum amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 9223372036854775806n; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#41) Creates a token with a fractional fee with a maximum amount of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 9223372036854775808n, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#42) Creates a token with a fractional fee with a maximum amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 18446744073709551615n, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#43) Creates a token with a fractional fee with a maximum amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 18446744073709551614n, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#44) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: -9223372036854775808n, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#45) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: -9223372036854775807n, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#46) Creates a token with a royalty fee with a numerator of 0", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 0, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#47) Creates a token with a royalty fee with a numerator of -1", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: -1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#48) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,807 (int64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 9223372036854775807n, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "ROYALTY_FRACTION_CANNOT_EXCEED_ONE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#49) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 9223372036854775806n, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "ROYALTY_FRACTION_CANNOT_EXCEED_ONE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#50) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 9223372036854775808n, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#51) Creates a token with a royalty fee with a numerator of 18,446,744,073,709,551,615 (uint64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 18446744073709551615n, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#52) Creates a token with a royalty fee with a numerator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 18446744073709551614n, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#53) Creates a token with a royalty fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: -9223372036854775808n, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#54) Creates a token with a royalty fee with a numerator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: -9223372036854775807n, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#55) Creates a token with a royalty fee with a denominator of 0", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 0, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#56) Creates a token with a royalty fee with a denominator of -1", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: -1, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#57) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,807 (int64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 9223372036854775807n; + const fallbackFeeAmount = 10; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + fallbackFee: { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + amount: fallbackFeeAmount + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); + }); + + it("(#58) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 9223372036854775806n; + const fallbackFeeAmount = 10; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + fallbackFee: { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + amount: fallbackFeeAmount + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); + }); + + it("(#59) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 9223372036854775808n, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#60) Creates a token with a royalty fee with a denominator of 18,446,744,073,709,551,615 (uint64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 18446744073709551615n, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#61) Creates a token with a royalty fee with a denominator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 18446744073709551614n, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#62) Creates a token with a royalty fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: -9223372036854775808n, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#63) Creates a token with a royalty fee with a denominator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: -9223372036854775807n, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#64) Creates a token with a royalty fee with a fallback fee with an amount of 0", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 0 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#65) Creates a token with a royalty fee with a fallback fee with an amount of -1", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: -1 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#66) Creates a token with a royalty fee with a fallback fee with an amount of 9,223,372,036,854,775,807 (int64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const fallbackFeeAmount = 9223372036854775807n; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + fallbackFee: { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + amount: fallbackFeeAmount + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); + }); + + it("(#67) Creates a token with a royalty fee with a fallback fee with an amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const fallbackFeeAmount = 9223372036854775806n; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + fallbackFee: { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + amount: fallbackFeeAmount + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); + }); + + it("(#68) Creates a token with a royalty fee with a fallback fee with an amount of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 9223372036854775808n + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#69) Creates a token with a royalty fee with a fallback fee with an amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 18446744073709551615n + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#70) Creates a token with a royalty fee with a fallback fee with an amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 18446744073709551614n + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#71) Creates a token with a royalty fee with a fallback fee with an amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: -9223372036854775808n + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#72) Creates a token with a royalty fee with a fallback fee with an amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: -9223372036854775807n + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#73) Creates a token with a fixed fee with a fee collector account that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: "123.456.789", + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#74) Creates a token with a fractional with a fee collector account that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: "123.456.789", + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#75) Creates a token with a royalty fee with a fee collector account that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: "123.456.789", + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#76) Creates a token with a royalty fee with fallback fee with a fee collector account that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: "123.456.789", + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#77) Creates a token with a fixed fee with an empty fee collector account", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: "", + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#78) Creates a token with a fractional with an empty fee collector account", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: "", + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#79) Creates a token with a royalty fee with an empty fee collector account", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: "", + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#80) Creates a token with a royalty fee with fallback fee with an empty fee collector account", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: "", + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#81) Creates a token with a fixed fee with a deleted fee collector account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }) + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: accountId, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + } + ], + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#82) Creates a token with a fractional fee with a deleted fee collector account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }) + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: accountId, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ], + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#83) Creates a token with a royalty fee with a deleted fee collector account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }) + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: accountId, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ], + commonTransactionParams: { + signers: [ + key + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); return; } assert.fail("Should throw an error"); }); - it("(#24) Creates a token with a fractional fee with the minimum amount higher than the maximum amount", async function () { + it("(#84) Creates a token with a royalty fee with a fallback fee with a deleted fee collector account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }) + if (response.status === "NOT_IMPLEMENTED") this.skip(); + try { - const response = await JSONRPCRequest("createToken", { + response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, @@ -3832,33 +5918,37 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - fractionalFee: { + royaltyFee: { numerator: 1, denominator: 10, - minimumAmount: 10, - maximumAmount: 1, - assessmentMethod: "inclusive" + fallbackFee: { + feeCollectorAccountId: accountId, + feeCollectorsExempt: false, + amount: 10 + } } } - ] + ], + commonTransactionParams: { + signers: [ + key + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); return; } assert.fail("Should throw an error"); }); - it("(#25) Creates a token with a fractional fee that is assessed to the receiver", async function () { + it("(#85) Creates a token with a fixed fee that is assessed with the created token", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const minAmount = 1; - const maxAmount = 10; - const assessmentMethod = "exclusive"; + const fixedFeeAmount = 10; + const denominatingTokenId = "0.0.0"; const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -3867,198 +5957,152 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minAmount, - maximumAmount: maxAmount, - assessmentMethod: assessmentMethod - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod); - }); - - it("(#26) Creates a token with a royalty fee with the minimum fractional amount", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }) - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 9223372036854775807n; - const fallbackFeeAmount = 10; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - royaltyFee: { - numerator: numerator, - denominator: denominator, - fallbackFee: { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - amount: fallbackFeeAmount - } + fixedFee: { + amount: fixedFeeAmount, + denominatingTokenId: denominatingTokenId } } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, fixedFeeAmount); }); - it("(#27) Creates a token with a royalty fee with the amount below the minimum fractional amount", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - + it("(#86) Creates a token with a fixed fee that is assessed with a token that doesn't exist", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", customFees: [ { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - royaltyFee: { - numerator: 0, - denominator: 9223372036854775807n, - fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - amount: 10 - } + fixedFee: { + amount: 10, + denominatingTokenId: "123.456.789" } } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); return; } assert.fail("Should throw an error"); }); - it("(#28) Creates a token with a royalty fee with the maximum fractional amount", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }) - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - + it("(#87) Creates a token with a fixed fee that is assessed with an empty token", async function () { try { - response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", customFees: [ { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - royaltyFee: { - numerator: 9223372036854775807n, - denominator: 1, - fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - amount: 10 - } + fixedFee: { + amount: 10, + denominatingTokenId: "" } } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "ROYALTY_FRACTION_CANNOT_EXCEED_ONE"); + assert.equal(err.code, -32603); return; } assert.fail("Should throw an error"); }); - it("(#29) Creates a token with a royalty fee with the amount above the maximum fractional amount", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + it("(#88) Creates a token with a fixed fee that is assessed with a deleted token", async function () { + let response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const tokenId = response.tokenId; + + response = await JSONRPCRequest("deleteToken", { + tokenId: tokenId }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", customFees: [ { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - royaltyFee: { - numerator: 9223372036854775808n, - denominator: 1, - fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - amount: 10 - } + fixedFee: { + amount: 10, + denominatingTokenId: tokenId } } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); return; } assert.fail("Should throw an error"); }); - it("(#30) Creates a token with a royalty fee with a 0 denominator", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + it("(#89) Creates a token with a fractional fee that is assessed to the receiver", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 10; + const assessmentMethod = "exclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#90) Creates a fungible token with a royalty fee", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", customFees: [ { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, royaltyFee: { numerator: 1, - denominator: 0, + denominator: 10, fallbackFee: { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, @@ -4070,48 +6114,51 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "FRACTION_DIVIDES_BY_ZERO"); + assert.equal(err.data.status, "CUSTOM_ROYALTY_FEE_ONLY_ALLOWED_FOR_NON_FUNGIBLE_UNIQUE"); return; } assert.fail("Should throw an error"); }); - it("(#31) Creates a fungible token with a royalty fee", async function () { + it("(#91) Creates an NFT with a fractional fee", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + try { const response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", customFees: [ { feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, feeCollectorsExempt: false, - royaltyFee: { + fractionalFee: { numerator: 1, denominator: 10, - fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - amount: 10 - } + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" } } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "CUSTOM_ROYALTY_FEE_ONLY_ALLOWED_FOR_NON_FUNGIBLE_UNIQUE"); + assert.equal(err.data.status, "CUSTOM_FRACTIONAL_FEE_ONLY_ALLOWED_FOR_FUNGIBLE_COMMON"); return; } assert.fail("Should throw an error"); }); - it("(#32) Creates a token with more than the maximum amount of fees allowed", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const amount = 10; + it("(#92) Creates a token with more than the maximum amount of fees allowed", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -4119,82 +6166,82 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, customFees: [ { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, fixedFee: { - amount: amount + amount: 10 } }, { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, fixedFee: { - amount: amount + amount: 10 } }, { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, fixedFee: { - amount: amount + amount: 10 } }, { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, fixedFee: { - amount: amount + amount: 10 } }, { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, fixedFee: { - amount: amount + amount: 10 } }, { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, fixedFee: { - amount: amount + amount: 10 } }, { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, fixedFee: { - amount: amount + amount: 10 } }, { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, fixedFee: { - amount: amount + amount: 10 } }, { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, fixedFee: { - amount: amount + amount: 10 } }, { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, fixedFee: { - amount: amount + amount: 10 } }, { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, fixedFee: { - amount: amount + amount: 10 } - }, + } ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); From d4b0897f6057ea7cbde6cdda6362fec47080dc34 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Wed, 4 Sep 2024 18:29:08 -0400 Subject: [PATCH 12/25] fix: custom fee tests to work Signed-off-by: Rob Walworth --- .../test_tokenCreateTransaction.js | 496 ++++++------------ 1 file changed, 168 insertions(+), 328 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index df4ee70..5d894ce 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -3046,11 +3046,11 @@ describe("TokenCreateTransaction", function () { assessmentMethod === customFractionalFee.assessmentMethod.toString().toLowerCase(); } - async function consensusNodeFeeEqualsCustomRoyaltyFee(customRoyaltyFee, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeCollectorAccountId, fixedFeeCollectorsExempt, fixedFeeAmount) { + async function consensusNodeFeeEqualsCustomRoyaltyFee(customRoyaltyFee, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeAmount) { return consensusNodeFeeEqualsCustomFee(customRoyaltyFee, feeCollectorAccountId, feeCollectorsExempt) && numerator === customRoyaltyFee.numerator && denominator === customRoyaltyFee.denominator && - consensusNodeFeeEqualsCustomFixedFee(customRoyaltyFee.fallbackFee, fixedFeeCollectorAccountId, fixedFeeCollectorsExempt, fixedFeeAmount); + fixedFeeAmount === customRoyaltyFee.fixedFeeAmount; } async function mirrorNodeFeeEqualsCustomFixedFee(customFixedFee, feeCollectorAccountId, amount) { @@ -3126,7 +3126,7 @@ describe("TokenCreateTransaction", function () { expect(foundMirrorNodeFee).to.be.true; } - async function verifyTokenCreationWithRoyaltyFee(tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeCollectorAccountId, fixedFeeCollectorsExempt, fixedFeeAmount) { + async function verifyTokenCreationWithRoyaltyFee(tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeAmount) { const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId).tokens[0]; @@ -3135,7 +3135,7 @@ describe("TokenCreateTransaction", function () { for (let i = 0; i < consensusNodeInfo.customFees.size(); i++) { if (consensusNodeInfo.customFees[i] instanceof CustomRoyaltyFee && - consensusNodeFeeEqualsCustomRoyaltyFee(consensusNodeInfo.customFees[i], feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeCollectorAccountId, fixedFeeCollectorsExempt, fixedFeeAmount)) { + consensusNodeFeeEqualsCustomRoyaltyFee(consensusNodeInfo.customFees[i], feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeAmount)) { foundConsensusNodeFee = true; break; } @@ -3432,61 +3432,65 @@ describe("TokenCreateTransaction", function () { }); it("(#12) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,807 (int64 max)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 9223372036854775807n, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 9223372036854775807n; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); - assert.fail("Should throw an error"); + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); }); - it("(#13) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 9223372036854775806n, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } + it("(#12) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 9223372036854775806n; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); - assert.fail("Should throw an error"); + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); }); it("(#14) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { @@ -3960,68 +3964,35 @@ describe("TokenCreateTransaction", function () { }); it("(#30) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,807 (int64 max)", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const minimumAmount = 9223372036854775807n; - const maximumAmount = 10; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minimumAmount, - maximumAmount: maximumAmount, - assessmentMethod: assessmentMethod + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 9223372036854775807n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); + return; + } - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + assert.fail("Should throw an error"); }); it("(#31) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const minimumAmount = 9223372036854775806n; - const maximumAmount = 10; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minimumAmount, - maximumAmount: maximumAmount, - assessmentMethod: assessmentMethod - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); - }); - - it("(#32) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -4034,7 +4005,7 @@ describe("TokenCreateTransaction", function () { fractionalFee: { numerator: 1, denominator: 10, - minimumAmount: 9223372036854775808n, + minimumAmount: 9223372036854775806n, maximumAmount: 10, assessmentMethod: "inclusive" } @@ -4043,14 +4014,14 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); return; } assert.fail("Should throw an error"); }); - it("(#33) Creates a token with a fractional fee with a minimum amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { + it("(#32) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -4063,7 +4034,7 @@ describe("TokenCreateTransaction", function () { fractionalFee: { numerator: 1, denominator: 10, - minimumAmount: 18446744073709551615n, + minimumAmount: 9223372036854775808n, maximumAmount: 10, assessmentMethod: "inclusive" } @@ -4079,7 +4050,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#34) Creates a token with a fractional fee with a minimum amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + it("(#33) Creates a token with a fractional fee with a minimum amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -4092,7 +4063,7 @@ describe("TokenCreateTransaction", function () { fractionalFee: { numerator: 1, denominator: 10, - minimumAmount: 18446744073709551614n, + minimumAmount: 18446744073709551615n, maximumAmount: 10, assessmentMethod: "inclusive" } @@ -4108,7 +4079,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#35) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + it("(#34) Creates a token with a fractional fee with a minimum amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -4121,7 +4092,7 @@ describe("TokenCreateTransaction", function () { fractionalFee: { numerator: 1, denominator: 10, - minimumAmount: -9223372036854775808n, + minimumAmount: 18446744073709551614n, maximumAmount: 10, assessmentMethod: "inclusive" } @@ -4137,7 +4108,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#36) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + it("(#35) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -4150,7 +4121,7 @@ describe("TokenCreateTransaction", function () { fractionalFee: { numerator: 1, denominator: 10, - minimumAmount: -9223372036854775807n, + minimumAmount: -9223372036854775808n, maximumAmount: 10, assessmentMethod: "inclusive" } @@ -4166,7 +4137,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#37) Creates a token with a fractional fee with a maximum amount of 0", async function () { + it("(#36) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -4179,8 +4150,8 @@ describe("TokenCreateTransaction", function () { fractionalFee: { numerator: 1, denominator: 10, - minimumAmount: 1, - maximumAmount: 0, + minimumAmount: -9223372036854775807n, + maximumAmount: 10, assessmentMethod: "inclusive" } } @@ -4188,13 +4159,44 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } assert.fail("Should throw an error"); }); + it("(#37) Creates a token with a fractional fee with a maximum amount of 0", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 0; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + it("(#38) Creates a token with a fractional fee with a maximum amount of -1", async function () { try { const response = await JSONRPCRequest("createToken", { @@ -4453,8 +4455,6 @@ describe("TokenCreateTransaction", function () { numerator: 0, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4492,8 +4492,6 @@ describe("TokenCreateTransaction", function () { numerator: -1, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4531,8 +4529,6 @@ describe("TokenCreateTransaction", function () { numerator: 9223372036854775807n, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4570,8 +4566,6 @@ describe("TokenCreateTransaction", function () { numerator: 9223372036854775806n, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4609,8 +4603,6 @@ describe("TokenCreateTransaction", function () { numerator: 9223372036854775808n, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4648,8 +4640,6 @@ describe("TokenCreateTransaction", function () { numerator: 18446744073709551615n, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4687,8 +4677,6 @@ describe("TokenCreateTransaction", function () { numerator: 18446744073709551614n, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4726,8 +4714,6 @@ describe("TokenCreateTransaction", function () { numerator: -9223372036854775808n, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4765,8 +4751,6 @@ describe("TokenCreateTransaction", function () { numerator: -9223372036854775807n, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4804,8 +4788,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 0, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4814,7 +4796,7 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); + assert.equal(err.data.status, "FRACTION_DIVIDES_BY_ZERO"); return; } @@ -4843,8 +4825,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: -1, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4882,12 +4862,10 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { + royaltyFee: { numerator: numerator, denominator: denominator, fallbackFee: { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, amount: fallbackFeeAmount } } @@ -4921,12 +4899,10 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { + royaltyFee: { numerator: numerator, denominator: denominator, fallbackFee: { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, amount: fallbackFeeAmount } } @@ -4960,8 +4936,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 9223372036854775808n, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -4999,8 +4973,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 18446744073709551615n, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -5038,8 +5010,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 18446744073709551614n, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -5077,8 +5047,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: -9223372036854775808n, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -5116,8 +5084,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: -9223372036854775807n, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -5155,8 +5121,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 0 } } @@ -5194,8 +5158,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: -1 } } @@ -5233,12 +5195,10 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { + royaltyFee: { numerator: numerator, denominator: denominator, fallbackFee: { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, amount: fallbackFeeAmount } } @@ -5272,12 +5232,10 @@ describe("TokenCreateTransaction", function () { { feeCollectorAccountId: feeCollectorAccountId, feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { + royaltyFee: { numerator: numerator, denominator: denominator, fallbackFee: { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, amount: fallbackFeeAmount } } @@ -5311,8 +5269,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 9223372036854775808n } } @@ -5350,8 +5306,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 18446744073709551615n } } @@ -5389,8 +5343,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 18446744073709551614n } } @@ -5428,8 +5380,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: -9223372036854775808n } } @@ -5467,8 +5417,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: -9223372036854775807n } } @@ -5538,12 +5486,20 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#75) Creates a token with a royalty fee with a fee collector account that doesn't exist", async function () { + it("(#75) Creates a token with a royalty fee with a fee collector account that doesn't exist", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + try { - const response = await JSONRPCRequest("createToken", { + response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", customFees: [ { feeCollectorAccountId: "123.456.789", @@ -5552,8 +5508,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -5569,38 +5523,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#76) Creates a token with a royalty fee with fallback fee with a fee collector account that doesn't exist", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - feeCollectorAccountId: "123.456.789", - feeCollectorsExempt: false, - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#77) Creates a token with a fixed fee with an empty fee collector account", async function () { + it("(#76) Creates a token with a fixed fee with an empty fee collector account", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -5625,7 +5548,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#78) Creates a token with a fractional with an empty fee collector account", async function () { + it("(#77) Creates a token with a fractional with an empty fee collector account", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -5654,12 +5577,20 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#79) Creates a token with a royalty fee with an empty fee collector account", async function () { + it("(#78) Creates a token with a royalty fee with an empty fee collector account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + try { - const response = await JSONRPCRequest("createToken", { + response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", customFees: [ { feeCollectorAccountId: "", @@ -5668,8 +5599,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, amount: 10 } } @@ -5685,38 +5614,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#80) Creates a token with a royalty fee with fallback fee with an empty fee collector account", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - feeCollectorAccountId: "", - feeCollectorsExempt: false, - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.code, -32603); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#81) Creates a token with a fixed fee with a deleted fee collector account", async function () { + it("(#79) Creates a token with a fixed fee with a deleted fee collector account", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -5769,7 +5667,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#82) Creates a token with a fractional fee with a deleted fee collector account", async function () { + it("(#80) Creates a token with a fractional fee with a deleted fee collector account", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -5826,7 +5724,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#83) Creates a token with a royalty fee with a deleted fee collector account", async function () { + it("(#81) Creates a token with a royalty fee with a deleted fee collector account", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -5855,6 +5753,8 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", customFees: [ { feeCollectorAccountId: accountId, @@ -5863,67 +5763,6 @@ describe("TokenCreateTransaction", function () { numerator: 1, denominator: 10, fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - amount: 10 - } - } - } - ], - commonTransactionParams: { - signers: [ - key - ] - } - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#84) Creates a token with a royalty fee with a fallback fee with a deleted fee collector account", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - response = await JSONRPCRequest("createAccount", { - key: key - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const accountId = response.accountId; - - response = await JSONRPCRequest("deleteAccount", { - deleteAccountId: accountId, - transferAccountId: process.env.OPERATOR_ACCOUNT_ID, - commonTransactionParams: { - signers: [ - key - ] - } - }) - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - feeCollectorAccountId: accountId, - feeCollectorsExempt: false, amount: 10 } } @@ -5944,7 +5783,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#85) Creates a token with a fixed fee that is assessed with the created token", async function () { + it("(#82) Creates a token with a fixed fee that is assessed with the created token", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const fixedFeeAmount = 10; @@ -5969,7 +5808,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, fixedFeeAmount); }); - it("(#86) Creates a token with a fixed fee that is assessed with a token that doesn't exist", async function () { + it("(#83) Creates a token with a fixed fee that is assessed with a token that doesn't exist", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -5995,7 +5834,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#87) Creates a token with a fixed fee that is assessed with an empty token", async function () { + it("(#84) Creates a token with a fixed fee that is assessed with an empty token", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -6021,7 +5860,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#88) Creates a token with a fixed fee that is assessed with a deleted token", async function () { + it("(#85) Creates a token with a fixed fee that is assessed with a deleted token", async function () { let response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", @@ -6059,7 +5898,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#89) Creates a token with a fractional fee that is assessed to the receiver", async function () { + it("(#86) Creates a token with a fractional fee that is assessed to the receiver", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 1; @@ -6090,7 +5929,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); }); - it("(#90) Creates a fungible token with a royalty fee", async function () { + it("(#87) Creates a fungible token with a royalty fee", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -6121,7 +5960,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#91) Creates an NFT with a fractional fee", async function () { + it("(#88) Creates an NFT with a fractional fee", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); @@ -6129,7 +5968,7 @@ describe("TokenCreateTransaction", function () { const key = response.key; try { - const response = await JSONRPCRequest("createToken", { + response = await JSONRPCRequest("createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, @@ -6158,7 +5997,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#92) Creates a token with more than the maximum amount of fees allowed", async function () { + it("(#89) Creates a token with more than the maximum amount of fees allowed", async function () { try { const response = await JSONRPCRequest("createToken", { name: "testname", @@ -6252,6 +6091,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); + }); describe("Pause Key", function () { From 19c8dcfddf51587b91dff22bbf9939b02be4f7f8 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Wed, 4 Sep 2024 18:41:49 -0400 Subject: [PATCH 13/25] fix: incorrectly numbered test Signed-off-by: Rob Walworth --- test/token-service/test_tokenCreateTransaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index 5d894ce..1b0cbc8 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -3462,7 +3462,7 @@ describe("TokenCreateTransaction", function () { verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); }); - it("(#12) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + it("(#13) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; const feeCollectorsExempt = false; const numerator = 9223372036854775806n; From a7084c1b4668998c9146f6e646097650a40fa25b Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Wed, 4 Sep 2024 18:52:50 -0400 Subject: [PATCH 14/25] style: fix white space Signed-off-by: Rob Walworth --- test/token-service/test_tokenCreateTransaction.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index 1b0cbc8..f22a515 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -6091,7 +6091,6 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - }); describe("Pause Key", function () { From fcee181a031aa66d56e69d0e9696f6fca74fcacc Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Mon, 9 Sep 2024 12:42:09 -0400 Subject: [PATCH 15/25] feat: finish token id and symbol tests Signed-off-by: Rob Walworth --- .../test_tokenUpdateTransaction.js | 6697 +++++++++++++++++ 1 file changed, 6697 insertions(+) create mode 100644 test/token-service/test_tokenUpdateTransaction.js diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js new file mode 100644 index 0000000..a084c43 --- /dev/null +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -0,0 +1,6697 @@ +import { JSONRPCRequest } from "../../client.js"; +import mirrorNodeClient from "../../mirrorNodeClient.js"; +import consensusInfoClient from "../../consensusInfoClient.js"; +import { setOperator } from "../../setup_Tests.js"; +import crypto from "crypto"; +import { assert, expect } from "chai"; + +// Needed to convert BigInts to JSON number format. +BigInt.prototype.toJSON = function () { + return JSON.rawJSON(this.toString()) +} + +/** + * Tests for TokenUpdateTransaction + */ +describe("TokenCreateTransaction", function () { + // Tests should not take longer than 30 seconds to fully execute. + this.timeout(30000); + + // Two tokens should be created. One immutable token (no admin key) and another mutable. + let immutableTokenId, mutableTokenId, mutableTokenAdminKey; + + // Some tests require an immutable token. Since it's immutable only one needs to be created. + before(async function () { + setOperator(process.env.OPERATOR_ACCOUNT_ID, process.env.OPERATOR_ACCOUNT_PRIVATE_KEY); + + let response = JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + initialSupply: 1000000, + tokenType: "ft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + immutableTokenId = response.tokenId; + }); + + beforeEach(async function () { + await setOperator(process.env.OPERATOR_ACCOUNT_ID, process.env.OPERATOR_ACCOUNT_PRIVATE_KEY); + + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + mutableTokenAdminKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + admin: mutableTokenAdminKey, + initialSupply: 1000000, + tokenType: "ft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + mutableTokenId = response.tokenId; + }); + afterEach(async function () { + await JSONRPCRequest("reset"); + }); + + describe("Token ID", function () { + async function verifyTokenUpdate(tokenId) { + let mirrorNodeData = await mirrorNodeClient.getTokenData(accountId); + let consensusNodeData = await consensusInfoClient.getTokenInfo(accountId); + expect(accountId).to.be.equal(mirrorNodeData.tokens[0].token); + expect(accountId).to.be.equal(consensusNodeData.tokens.toString()); + } + + it("(#1) Updates an immutable token with no updates", async function () { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenUpdate(response.tokenId); + }); + + it("(#2) Updates a mutable token with no updates", async function () { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenUpdate(response.tokenId); + }); + + it("(#3) Updates a token with no token ID", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_ID"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Symbol", function () { + async function verifyTokenSymbolUpdate(tokenId, symbol) { + expect(symbol).to.equal(await consensusInfoClient.getTokenInfo(tokenId).symbol); + expect(symbol).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].symbol); + } + + it("(#1) Updates an immutable token with a symbol", async function () { + try { + const response = await JSONRPCRequest("createToken", { + tokenId: immutableTokenId, + symbol: "t" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Updates a mutable token with a symbol that is the minimum length", async function () { + const symbol = "t"; + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + symbol: symbol, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenSymbolUpdate(response.tokenId, symbol); + }); + + it("(#3) Updates a mutable token with a symbol that is empty", async function () { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + symbol: "", + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Symbol shouldn't change and should still remain as "testsymbol". + verifyTokenSymbolUpdate(response.tokenId, "testsymbol"); + }); + + it("(#4) Updates a mutable token with a symbol that is the maximum length", async function () { + const symbol = "This is a really long symbol but it is still valid because it is 100 characters exactly on the money" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + symbol: symbol, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenSymbolUpdate(response.tokenId, symbol); + }); + + it("(#5) Updates a mutable token with a symbol that exceeds the maximum length", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + symbol: "This is a long symbol that is not valid because it exceeds 100 characters and it should fail the test", + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_SYMBOL_TOO_LONG"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#6) Updates a mutable token with a valid symbol without signing with the token's admin key", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + symbol: "t" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Name", function () { + async function verifyTokenNameUpdate(tokenId, name) { + expect(name).to.equal(await consensusInfoClient.getTokenInfo(tokenId).name); + expect(name).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].name); + } + + it("(#1) Updates an immutable token with a symbol", async function () { + try { + const response = await JSONRPCRequest("createToken", { + tokenId: immutableTokenId, + symbol: "t" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Updates a mutable token with a symbol that is the minimum length", async function () { + const symbol = "t"; + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + symbol: symbol, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenSymbolUpdate(response.tokenId, symbol); + }); + + it("(#3) Updates a mutable token with a symbol that is empty", async function () { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + symbol: "", + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Symbol shouldn't change and should still remain as "testsymbol". + verifyTokenSymbolUpdate(response.tokenId, "testsymbol"); + }); + + it("(#4) Updates a mutable token with a symbol that is the maximum length", async function () { + const symbol = "This is a really long symbol but it is still valid because it is 100 characters exactly on the money" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + symbol: symbol, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenSymbolUpdate(response.tokenId, symbol); + }); + + it("(#5) Updates a mutable token with a symbol that exceeds the maximum length", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + symbol: "This is a long symbol that is not valid because it exceeds 100 characters and it should fail the test", + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_SYMBOL_TOO_LONG"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#6) Updates a mutable token with a valid symbol without signing with the token's admin key", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + symbol: "t" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Decimals", function () { + async function verifyTokenCreationWithDecimals(tokenId, decimals) { + expect(decimals).to.equal(await consensusInfoClient.getTokenInfo(tokenId).decimals); + expect(decimals).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].decimals); + } + + it("(#1) Creates a fungible token with 0 decimals", async function () { + const decimals = 0; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithDecimals(response.tokenId, decimals); + }); + + it("(#2) Creates a fungible token with -1 decimals", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: -1, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a fungible token with 2,147,483,647 (int32 max) decimals", async function () { + const decimals = 2147483647; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithDecimals(response.tokenId, decimals); + }); + + it("(#4) Creates a fungible token with 2,147,483,646 (int32 max - 1) decimals", async function () { + const decimals = 2147483646; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithDecimals(response.tokenId, decimals); + }); + + it("(#5) Creates a fungible token with 2,147,483,648 (int32 max + 1) decimals", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: 2147483648, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#6) Creates a fungible token with 4,294,967,295 (uint32 max) decimals", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: 4294967295, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#7) Creates a fungible token with 4,294,967,294 (uint32 max - 1) decimals", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: 4294967294, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#8) Creates a fungible token with -2,147,483,648 (int32 min) decimals", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: -2147483648, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a fungible token with -2,147,483,647 (int32 min + 1) decimals", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: -2147483647, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#10) Creates an NFT with a decimal amount of zero", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const decimals = 0; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithDecimals(response.tokenId, decimals); + }); + + it("(#11) Creates an NFT with a nonzero decimal amount", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: 3, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Initial Supply", function () { + async function verifyTokenCreationWithInitialSupply(tokenId, initialSupply) { + expect(initialSupply).to.equal(await consensusInfoClient.getTokenInfo(tokenId).totalSupply); + expect(initialSupply).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].initial_supply); + } + + it("(#1) Creates a fungible token with 0 initial supply", async function () { + const initialSupply = 0; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: initialSupply, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); + }); + + it("(#2) Creates a fungible token with -1 initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: -1, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a fungible token with 9,223,372,036,854,775,807 (int64 max) initial supply", async function () { + const initialSupply = 9223372036854775807n; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: initialSupply, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); + }); + + it("(#4) Creates a fungible token with 9,223,372,036,854,775,806 (int64 max - 1) initial supply", async function () { + const initialSupply = 9223372036854775806n; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: initialSupply, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); + }); + + it("(#5) Creates a fungible token with 9,223,372,036,854,775,808 (int64 max + 1) initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: 9223372036854775808n, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#6) Creates a fungible token with 18,446,744,073,709,551,615 (uint64 max) initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: 18446744073709551615n, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#7) Creates a fungible token with 18,446,744,073,709,551,614 (uint64 max - 1) initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: 18446744073709551614n, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#8) Creates a fungible token with -9,223,372,036,854,775,808 (int64 min) initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: -9223372036854775808n, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a fungible token with -9,223,372,036,854,775,807 (int64 min + 1) initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: -9223372036854775807n, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#10) Creates a fungible token with a valid initial supply and decimals", async function () { + const decimals = 2; + const initialSupply = 1000000; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + initialSupply: initialSupply, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply / (10 ** decimals)); + }); + + it("(#11) Creates a fungible token with a valid initial supply and more decimals", async function () { + const decimals = 6; + const initialSupply = 1000000; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + decimals: decimals, + initialSupply: initialSupply, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply / (10 ** decimals)); + }); + + it("(#12) Creates an NFT with an initial supply of zero", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const initialSupply = 0; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: initialSupply, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); + }); + + it("(#13) Creates an NFT with an initial supply of zero without a supply key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: 0, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#14) Creates an NFT with a nonzero initial supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + initialSupply: 3, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Treasury Account", function () { + async function verifyTokenCreationWithTreasuryAccount(tokenId, treasuryAccountId) { + expect(treasuryAccountId).to.equal(await consensusInfoClient.getTokenInfo(tokenId).treasuryAccountId.toString()); + expect(treasuryAccountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].treasury_account_id); + } + + it("(#1) Creates a token with a treasury account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: accountId, + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithTreasuryAccount(response.tokenId, accountId); + }); + + it("(#2) Creates a token with a treasury account without signing with the account's private key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: accountId + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a token with a treasury account that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: "123.456.789" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_ACCOUNT_ID"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#4) Creates a token with a treasury account that is deleted", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: accountId, + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TREASURY_ACCOUNT_FOR_TOKEN"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Admin Key", function () { + async function verifyTokenCreationWithAdminKey(tokenId, adminKey) { + expect(adminKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).adminKey.toStringDer()); + expect(adminKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].admin_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its admin key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + adminKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its admin key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + adminKey: publicKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its admin key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + adminKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its admin key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + adminKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { + const keyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + }); + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + adminKey: keyList.key, + commonTransactionParams: { + signers: [ + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithAdminKey(response.tokenId, keyList.key); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its admin key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + adminKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithAdminKey(response.tokenId, nestedKeyList.key); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + adminKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithAdminKey(response.tokenId, thresholdKey.key); + }); + + it("(#8) Creates a token with a valid key as its admin key but doesn't sign with it", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + adminKey: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with an invalid key as its admin key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + adminKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("KYC Key", function () { + async function verifyTokenCreationWithKycKey(tokenId, kycKey) { + expect(kycKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).kycKey.toStringDer()); + expect(kycKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].kyc_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + kycKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + kycKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + kycKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + kycKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + kycKey: keyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithKycKey(response.tokenId, keyList); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + kycKey: nestedKeyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithKycKey(response.tokenId, nestedKeyList); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + kycKey: thresholdKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithKycKey(response.tokenId, thresholdKey); + }); + + it("(#8) Creates a token with an invalid key as its KYC key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + kycKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Freeze Key", function () { + async function verifyTokenCreationWithFreezeKey(tokenId, freezeKey) { + expect(freezeKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).freezeKey.toStringDer()); + expect(freezeKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].freeze_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: keyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFreezeKey(response.tokenId, keyList); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: nestedKeyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFreezeKey(response.tokenId, nestedKeyList); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: thresholdKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFreezeKey(response.tokenId, thresholdKey); + }); + + it("(#8) Creates a token with an invalid key as its freeze key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Wipe Key", function () { + async function verifyTokenCreationWithWipeKey(tokenId, wipeKey) { + expect(wipeKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).wipeKey.toStringDer()); + expect(wipeKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].wipe_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: keyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithWipeKey(response.tokenId, keyList); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: nestedKeyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithWipeKey(response.tokenId, nestedKeyList); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: thresholdKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithWipeKey(response.tokenId, thresholdKey); + }); + + it("(#8) Creates a token with an invalid key as its wipe key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + wipeKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Supply Key", function () { + async function verifyTokenCreationWithSupplyKey(tokenId, supplyKey) { + expect(supplyKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).supplyKey.toStringDer()); + expect(supplyKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].supply_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: keyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithSupplyKey(response.tokenId, keyList); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: nestedKeyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithSupplyKey(response.tokenId, nestedKeyList); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: thresholdKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithSupplyKey(response.tokenId, thresholdKey.key); + }); + + it("(#8) Creates a token with an invalid key as its supply key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Freeze Default", function () { + async function verifyTokenCreationWithFreezeDefault(tokenId, freezeDefault) { + expect(freezeDefault).to.equal(await consensusInfoClient.getTokenInfo(tokenId).freezeDefault); + expect(freezeDefault).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].freeze_default); + } + + it("(#1) Creates a token with a frozen default status", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const freezeDefault = true; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeKey: key, + freezeDefault: freezeDefault + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFreezeDefault(response.tokenId, freezeDefault); + }); + + it("(#2) Creates a token with a frozen default status and no freeze key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeDefault: true + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_FREEZE_KEY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a token with an unfrozen default status", async function () { + const freezeDefault = false; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + freezeDefault: freezeDefault + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFreezeDefault(response.tokenId, freezeDefault); + }); + }); + + describe("Expiration Time", function () { + async function verifyTokenCreationWithExpirationTime(tokenId, expirationTime) { + expect(expirationTime).to.equal(await consensusInfoClient.getTokenInfo(tokenId).expirationTime); + expect(expirationTime).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].expiry_timestamp); + } + + it("(#1) Creates a token with an expiration time of 0 seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 0 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Creates a token with an expiration time of -1 seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: -1 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a token with an expiration time of 9,223,372,036,854,775,807 (int64 max) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 9223372036854775807n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#4) Creates a token with an expiration time of 9,223,372,036,854,775,806 (int64 max - 1) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 9223372036854775806n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#5) Creates a token with an expiration time of 9,223,372,036,854,775,808 (int64 max + 1) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 9223372036854775808n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#6) Creates a token with an expiration time of 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 18446744073709551615n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#7) Creates a token with an expiration time of 18,446,744,073,709,551,614 (uint64 max - 1) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: 18446744073709551614n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#8) Creates a token with an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: -9223372036854775808n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: -9223372036854775807n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#10) Creates a token with an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { + const expirationTime = parseInt((Date.now() / 1000) + 5184000); + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: expirationTime + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithExpirationTime(response.tokenId, expirationTime); + }); + + it("(#11) Creates a token with an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { + const expirationTime = parseInt((Date.now() / 1000) + 2592000); + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: expirationTime + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithExpirationTime(response.tokenId, expirationTime); + }); + + //it("(#12) Creates a token with an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { + // try { + // const response = await JSONRPCRequest("createToken", { + // name: "testname", + // symbol: "testsymbol", + // treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + // expirationTime: (Date.now() / 1000) + 2591999 + // }); + // if (response.status === "NOT_IMPLEMENTED") this.skip(); + // } catch (err) { + // assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + // return; + // } + // + // assert.fail("Should throw an error"); + //}); + + it("(#13) Creates a token with an expiration time of 8,000,001 seconds from the current time", async function () { + const expirationTime = parseInt((Date.now() / 1000) + 8000001); + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: expirationTime + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithExpirationTime(response.tokenId, expirationTime); + }); + + it("(#14) Creates a token with an expiration time of 8,000,002 seconds from the current time", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime: (Date.now() / 1000) + 8000002 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Auto Renew Account", function () { + it ("(#1) Creates a token with an auto renew account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const tokenId = response.tokenId; + + expect(accountId).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewAccountId.toString()); + expect(accountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_account); + }); + + it ("(#2) Creates a token with an auto renew account without signing with the account's key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccountId: accountId + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it ("(#3) Creates a token with an auto renew account that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccountId: "123.456.789" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); + return; + } + + assert.fail("Should throw an error"); + }); + + it ("(#4) Creates a token with an empty auto renew account", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccountId: "" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it ("(#5) Creates a token with an auto renew account that is deleted", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + describe("Auto Renew Period", function () { + async function verifyTokenCreationWithAutoRenewPeriod(tokenId, autoRenewPeriod) { + expect(autoRenewPeriod).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewPeriod); + expect(autoRenewPeriod).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_period); + } + + it ("(#1) Creates a token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { + const autoRenewPeriod = 5184000 + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: autoRenewPeriod + }); + + verifyTokenCreationWithAutoRenewPeriod(response.tokenId, autoRenewPeriod); + }); + + it ("(#2) Creates a token with an auto renew period set to -1 seconds", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: -1 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); + return; + } + + assert.fail("Should throw an error"); + }); + + it ("(#3) Creates a token with an auto renew period set to the minimum period of 30 days (2,592,000 seconds)", async function () { + const autoRenewPeriod = 2592000; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: autoRenewPeriod + }); + + verifyTokenCreationWithAutoRenewPeriod(response.tokenId, autoRenewPeriod); + }); + + it ("(#4) Creates a token with an auto renew period set to the minimum period of 30 days minus one second (2,591,999 seconds)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: 2591999 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); + return; + } + + assert.fail("Should throw an error"); + }); + + it ("(#5) Creates a token with an auto renew period set to the maximum period of 8,000,001 seconds", async function () { + const autoRenewPeriod = 8000001; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: autoRenewPeriod + }); + + verifyTokenCreationWithAutoRenewPeriod(response.tokenId, autoRenewPeriod); + }); + + it ("(#6) Creates a token with an auto renew period set to the maximum period plus one second (8,000,002 seconds)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + autoRenewPeriod: 8000002 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Memo", function () { + async function verifyTokenCreationWithMemo(tokenId, memo) { + expect(memo).to.equal(await consensusInfoClient.getTokenInfo(tokenId).memo); + expect(memo).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].memo); + } + + it ("(#1) Creates a token with a memo that is a valid length", async function () { + const memo = "testmemo" + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + memo: memo + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMemo(response.tokenId, memo); + }); + + it ("(#2) Creates a token with a memo that is the minimum length", async function () { + const memo = "" + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + memo: memo + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMemo(response.tokenId, memo); + }); + + it ("(#3) Creates a token with a memo that is the maximum length", async function () { + const memo = "This is a really long memo but it is still valid because it is 100 characters exactly on the money!!" + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + memo: memo + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMemo(response.tokenId, memo); + }); + + it ("(#4) Creates a token with a memo that exceeds the maximum length", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + memo: "This is a long memo that is not valid because it exceeds 100 characters and it should fail the test!!" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "MEMO_TOO_LONG"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Token Type", function () { + async function verifyTokenCreationWithTokenType(tokenId, type) { + expect(type).to.equal(await consensusInfoClient.getTokenInfo(tokenId).type); + expect(type).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].type); + } + + it ("(#1) Creates a fungible token", async function () { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "ft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithTokenType(response.tokenId, "FUNGIBLE_COMMON"); + }); + + it ("(#2) Creates an NFT", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + });; + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithTokenType(response.tokenId, "NON_FUNGIBLE_UNIQUE"); + }); + + it ("(#3) Creates an NFT without a supply key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + tokenType: "nft" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Supply Type", function () { + async function verifyTokenCreationWithSupplyType(tokenId, type) { + expect(type).to.equal(await consensusInfoClient.getTokenInfo(tokenId).supplyType); + expect(type).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].supply_type); + } + + it ("(#1) Creates a token with a finite supply", async function () { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: 1000000 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithSupplyType(response.tokenId, "FINITE"); + }) + + it ("(#2) Creates a token with an infinite supply", async function () { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "infinite" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithSupplyType(response.tokenId, "INFINITE"); + }) + }); + + describe("Max Supply", function () { + async function verifyTokenCreationWithMaxSupply(tokenId, maxSupply) { + expect(maxSupply).to.equal(await consensusInfoClient.getTokenInfo(tokenId).maxSupply); + expect(maxSupply).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].max_supply); + } + + it("(#1) Creates a token with 0 max supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: 0 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Creates a token with -1 max supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: -1 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a token with 9,223,372,036,854,775,807 (int64 max) max supply", async function () { + const maxSupply = 9223372036854775807n; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: maxSupply + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); + }); + + it("(#4) Creates a token with 9,223,372,036,854,775,806 (int64 max - 1) max supply", async function () { + const maxSupply = 9223372036854775806n; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: maxSupply + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); + }); + + it("(#5) Creates a token with 9,223,372,036,854,775,808 (int64 max + 1) max supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: 9223372036854775808n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#6) Creates a token with 18,446,744,073,709,551,615 (uint64 max) max supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: 18446744073709551615n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#7) Creates a token with 18,446,744,073,709,551,614 (uint64 max) max supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: 18446744073709551614n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#8) Creates a token with -9,223,372,036,854,775,808 (int64 min) max supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: -9223372036854775808n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with -9,223,372,036,854,775,807 (int64 min) max supply", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "finite", + maxSupply: -9223372036854775807n + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#10) Creates a token with a max supply and an infinite supply type", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyType: "infinite", + maxSupply: 1000000 + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Fee Schedule Key", function () { + async function verifyTokenCreationWithFeeScheduleKey(tokenId, feeScheduleKey) { + expect(feeScheduleKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).feeScheduleKey.toStringDer()); + expect(feeScheduleKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].fee_schedule_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: keyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFeeScheduleKey(response.tokenId, keyList); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: nestedKeyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFeeScheduleKey(response.tokenId, nestedKeyList); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: thresholdKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFeeScheduleKey(response.tokenId, thresholdKey); + }); + + it("(#8) Creates a token with an invalid key as its fee schedule key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeScheduleKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Custom Fees", function () { + async function consensusNodeFeeEqualsCustomFee(customFee, feeCollectorAccountId, feeCollectorsExempt) { + return feeCollectorAccountId === customFee.feeCollectorAccountId.toString() && + feeCollectorsExempt === customFee.allCollectorsAreExempt; + } + + async function consensusNodeFeeEqualsCustomFixedFee(customFixedFee, feeCollectorAccountId, feeCollectorsExempt, amount) { + return consensusNodeFeeEqualsCustomFee(customFixedFee, feeCollectorAccountId, feeCollectorsExempt) && + amount === customFixedFee.amount; + } + + async function consensusNodeFeeEqualsCustomFractionalFee(customFractionalFee, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod) { + return consensusNodeFeeEqualsCustomFee(customFractionalFee, feeCollectorAccountId, feeCollectorsExempt) && + numerator === customFractionalFee.numerator && + denominator === customFractionalFee.denominator && + minAmount === customFractionalFee.minimumAmount && + maxAmount === customFractionalFee.maximumAmount && + assessmentMethod === customFractionalFee.assessmentMethod.toString().toLowerCase(); + } + + async function consensusNodeFeeEqualsCustomRoyaltyFee(customRoyaltyFee, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeAmount) { + return consensusNodeFeeEqualsCustomFee(customRoyaltyFee, feeCollectorAccountId, feeCollectorsExempt) && + numerator === customRoyaltyFee.numerator && + denominator === customRoyaltyFee.denominator && + fixedFeeAmount === customRoyaltyFee.fixedFeeAmount; + } + + async function mirrorNodeFeeEqualsCustomFixedFee(customFixedFee, feeCollectorAccountId, amount) { + return feeCollectorAccountId === customFixedFee.collector_account_id && + amount === customFixedFee.amount; + } + + async function mirrorNodeFeeEqualsCustomFractionalFee(customFractionalFee, feeCollectorAccountId, numerator, denominator, minAmount, maxAmount, assessmentMethod) { + return feeCollectorAccountId === customFractionalFee.collector_account_id && + numerator === customFractionalFee.amount.numerator && + denominator === customFractionalFee.amount.denominator && + minAmount === customFractionalFee.minimum && + maxAmount === customFractionalFee.maximum && + ((assessmentMethod === "exclusive") === customFractionalFee.net_of_transfer); + } + + async function mirrorNodeFeeEqualsCustomRoyaltyFee(customRoyaltyFee, feeCollectorAccountId, numerator, denominator, fixedFeeAmount) { + return feeCollectorAccountId === customRoyaltyFee.collector_account_id && + numerator === customRoyaltyFee.amount.numerator && + denominator === customRoyaltyFee.amount.denominator && + fixedFeeAmount === customRoyaltyFee.fallback_fee.amount; + } + + async function verifyTokenCreationWithFixedFee(tokenId, feeCollectorAccountId, feeCollectorsExempt, amount) { + const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); + const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId).tokens[0]; + + let foundConsensusNodeFee = false; + let foundMirrorNodeFee = false; + + for (let i = 0; i < consensusNodeInfo.customFees.size(); i++) { + if (consensusNodeInfo.customFees[i] instanceof CustomFixedFee && + consensusNodeFeeEqualsCustomFixedFee(consensusNodeInfo.customFees[i], feeCollectorAccountId, feeCollectorsExempt, amount)) { + foundConsensusNodeFee = true; + break; + } + } + + for (let i = 0; i < mirrorNodeInfo.custom_fees.fixed_fees.size(); i++) { + if (mirrorNodeFeeEqualsCustomFixedFee(mirrorNodeInfo.custom_fees.fixed_fees[i], feeCollectorAccountId, amount)) { + foundMirrorNodeFee = true; + break; + } + } + + expect(foundConsensusNodeFee).to.be.true; + expect(foundMirrorNodeFee).to.be.true; + } + + async function verifyTokenCreationWithFractionalFee(tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod) { + const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); + const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId).tokens[0]; + + let foundConsensusNodeFee = false; + let foundMirrorNodeFee = false; + + for (let i = 0; i < consensusNodeInfo.customFees.size(); i++) { + if (consensusNodeInfo.customFees[i] instanceof CustomFractionalFee && + consensusNodeFeeEqualsCustomFractionalFee(consensusNodeInfo.customFees[i], feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod)) { + foundConsensusNodeFee = true; + break; + } + } + + for (let i = 0; i < mirrorNodeInfo.custom_fees.fractional_fees.size(); i++) { + if (mirrorNodeFeeEqualsCustomFractionalFee(mirrorNodeInfo.custom_fees.fractional_fees[i], feeCollectorAccountId, numerator, denominator, minAmount, maxAmount, assessmentMethod)) { + foundMirrorNodeFee = true; + break; + } + } + + expect(foundConsensusNodeFee).to.be.true; + expect(foundMirrorNodeFee).to.be.true; + } + + async function verifyTokenCreationWithRoyaltyFee(tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeAmount) { + const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); + const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId).tokens[0]; + + let foundConsensusNodeFee = false; + let foundMirrorNodeFee = false; + + for (let i = 0; i < consensusNodeInfo.customFees.size(); i++) { + if (consensusNodeInfo.customFees[i] instanceof CustomRoyaltyFee && + consensusNodeFeeEqualsCustomRoyaltyFee(consensusNodeInfo.customFees[i], feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeAmount)) { + foundConsensusNodeFee = true; + break; + } + } + + for (let i = 0; i < mirrorNodeInfo.custom_fees.fractional_fees.size(); i++) { + if (mirrorNodeFeeEqualsCustomRoyaltyFee(mirrorNodeInfo.custom_fees.fractional_fees[i], feeCollectorAccountId, numerator, denominator, fixedFeeAmount)) { + foundMirrorNodeFee = true; + break; + } + } + + expect(foundConsensusNodeFee).to.be.true; + expect(foundMirrorNodeFee).to.be.true; + } + + it("(#1) Creates a token with a fixed fee with an amount of 0", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 0 + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Creates a token with a fixed fee with an amount of -1", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: -1 + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#3) Creates a token with a fixed fee with an amount of 9,223,372,036,854,775,807 (int64 max)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const amount = 9223372036854775807n; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fixedFee: { + amount: amount + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); + }); + + it("(#4) Creates a token with a fixed fee with an amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const amount = 9223372036854775806n; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fixedFee: { + amount: amount + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); + }); + + it("(#5) Creates a token with a fixed fee with an amount of 9,223,372,036,854,775,8068 (int64 max + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 9223372036854775808n + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#6) Creates a token with a fixed fee with an amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 18446744073709551615n + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#7) Creates a token with a fixed fee with an amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 18446744073709551614n + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#8) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: -9223372036854775808n + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#9) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: -9223372036854775807n + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#10) Creates a token with a fractional fee with a numerator of 0", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 0, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#11) Creates a token with a fractional fee with a numerator of -1", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: -1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#12) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,807 (int64 max)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 9223372036854775807n; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#13) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 9223372036854775806n; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#14) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 9223372036854775808n, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#15) Creates a token with a fractional fee with a numerator of 18,446,744,073,709,551,615 (uint64 max)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 18446744073709551615n, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#16) Creates a token with a fractional fee with a numerator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 18446744073709551614n, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#17) Creates a token with a fractional fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: -9223372036854775808n, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#18) Creates a token with a fractional fee with a numerator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: -9223372036854775807n, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#19) Creates a token with a fractional fee with a denominator of 0", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 0, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "FRACTION_DIVIDES_BY_ZERO"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#20) Creates a token with a fractional fee with a denominator of -1", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: -1, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#21) Creates a token with a fractional fee with a denominator of 9,223,372,036,854,775,807 (int64 max)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 9223372036854775807n; + const minimumAmount = 1; + const maximumAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#22) Creates a token with a fractional fee with a denominator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 9223372036854775806n; + const minimumAmount = 1; + const maximumAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#23) Creates a token with a fractional fee with a denominator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 9223372036854775808n, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#24) Creates a token with a fractional fee with a denominator of 18,446,744,073,709,551,615 (uint64 max)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 18446744073709551615n, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#25) Creates a token with a fractional fee with a denominator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 18446744073709551614n, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#26) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: -9223372036854775808n, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#27) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: -9223372036854775807n, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#28) Creates a token with a fractional fee with a minimum amount of 0", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 0; + const maximumAmount = 10; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#29) Creates a token with a fractional fee with a minimum amount of -1", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: -1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#30) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,807 (int64 max)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 9223372036854775807n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#31) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 9223372036854775806n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#32) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 9223372036854775808n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#33) Creates a token with a fractional fee with a minimum amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 18446744073709551615n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#34) Creates a token with a fractional fee with a minimum amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 18446744073709551614n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#35) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: -9223372036854775808n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#36) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: -9223372036854775807n, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#37) Creates a token with a fractional fee with a maximum amount of 0", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 0; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#38) Creates a token with a fractional fee with a maximum amount of -1", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: -1, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#39) Creates a token with a fractional fee with a maximum amount of 9,223,372,036,854,775,807 (int64 max)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 9223372036854775807n; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#40) Creates a token with a fractional fee with a maximum amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 9223372036854775806n; + const assessmentMethod = "inclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#41) Creates a token with a fractional fee with a maximum amount of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 9223372036854775808n, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#42) Creates a token with a fractional fee with a maximum amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 18446744073709551615n, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#43) Creates a token with a fractional fee with a maximum amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 18446744073709551614n, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#44) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: -9223372036854775808n, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#45) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: -9223372036854775807n, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#46) Creates a token with a royalty fee with a numerator of 0", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 0, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#47) Creates a token with a royalty fee with a numerator of -1", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: -1, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#48) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,807 (int64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 9223372036854775807n, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "ROYALTY_FRACTION_CANNOT_EXCEED_ONE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#49) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 9223372036854775806n, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "ROYALTY_FRACTION_CANNOT_EXCEED_ONE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#50) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 9223372036854775808n, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#51) Creates a token with a royalty fee with a numerator of 18,446,744,073,709,551,615 (uint64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 18446744073709551615n, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#52) Creates a token with a royalty fee with a numerator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 18446744073709551614n, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#53) Creates a token with a royalty fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: -9223372036854775808n, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#54) Creates a token with a royalty fee with a numerator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: -9223372036854775807n, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#55) Creates a token with a royalty fee with a denominator of 0", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 0, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "FRACTION_DIVIDES_BY_ZERO"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#56) Creates a token with a royalty fee with a denominator of -1", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: -1, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#57) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,807 (int64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 9223372036854775807n; + const fallbackFeeAmount = 10; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + royaltyFee: { + numerator: numerator, + denominator: denominator, + fallbackFee: { + amount: fallbackFeeAmount + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); + }); + + it("(#58) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 9223372036854775806n; + const fallbackFeeAmount = 10; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + royaltyFee: { + numerator: numerator, + denominator: denominator, + fallbackFee: { + amount: fallbackFeeAmount + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); + }); + + it("(#59) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 9223372036854775808n, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#60) Creates a token with a royalty fee with a denominator of 18,446,744,073,709,551,615 (uint64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 18446744073709551615n, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#61) Creates a token with a royalty fee with a denominator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 18446744073709551614n, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#62) Creates a token with a royalty fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: -9223372036854775808n, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#63) Creates a token with a royalty fee with a denominator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: -9223372036854775807n, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#64) Creates a token with a royalty fee with a fallback fee with an amount of 0", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + amount: 0 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#65) Creates a token with a royalty fee with a fallback fee with an amount of -1", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + amount: -1 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#66) Creates a token with a royalty fee with a fallback fee with an amount of 9,223,372,036,854,775,807 (int64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const fallbackFeeAmount = 9223372036854775807n; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + royaltyFee: { + numerator: numerator, + denominator: denominator, + fallbackFee: { + amount: fallbackFeeAmount + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); + }); + + it("(#67) Creates a token with a royalty fee with a fallback fee with an amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const fallbackFeeAmount = 9223372036854775806n; + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + royaltyFee: { + numerator: numerator, + denominator: denominator, + fallbackFee: { + amount: fallbackFeeAmount + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); + }); + + it("(#68) Creates a token with a royalty fee with a fallback fee with an amount of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + amount: 9223372036854775808n + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#69) Creates a token with a royalty fee with a fallback fee with an amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + amount: 18446744073709551615n + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#70) Creates a token with a royalty fee with a fallback fee with an amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + amount: 18446744073709551614n + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#71) Creates a token with a royalty fee with a fallback fee with an amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + amount: -9223372036854775808n + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#72) Creates a token with a royalty fee with a fallback fee with an amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + amount: -9223372036854775807n + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#73) Creates a token with a fixed fee with a fee collector account that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: "123.456.789", + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#74) Creates a token with a fractional with a fee collector account that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: "123.456.789", + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#75) Creates a token with a royalty fee with a fee collector account that doesn't exist", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: "123.456.789", + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#76) Creates a token with a fixed fee with an empty fee collector account", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: "", + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#77) Creates a token with a fractional with an empty fee collector account", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: "", + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#78) Creates a token with a royalty fee with an empty fee collector account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: "", + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#79) Creates a token with a fixed fee with a deleted fee collector account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }) + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: accountId, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + } + ], + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#80) Creates a token with a fractional fee with a deleted fee collector account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }) + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: accountId, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ], + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#81) Creates a token with a royalty fee with a deleted fee collector account", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }) + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: accountId, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + amount: 10 + } + } + } + ], + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#82) Creates a token with a fixed fee that is assessed with the created token", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const fixedFeeAmount = 10; + const denominatingTokenId = "0.0.0"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fixedFee: { + amount: fixedFeeAmount, + denominatingTokenId: denominatingTokenId + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, fixedFeeAmount); + }); + + it("(#83) Creates a token with a fixed fee that is assessed with a token that doesn't exist", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10, + denominatingTokenId: "123.456.789" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#84) Creates a token with a fixed fee that is assessed with an empty token", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10, + denominatingTokenId: "" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#85) Creates a token with a fixed fee that is assessed with a deleted token", async function () { + let response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const tokenId = response.tokenId; + + response = await JSONRPCRequest("deleteToken", { + tokenId: tokenId + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10, + denominatingTokenId: tokenId + } + } + ] + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#86) Creates a token with a fractional fee that is assessed to the receiver", async function () { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorsExempt = false; + const numerator = 1; + const denominator = 10; + const minimumAmount = 1; + const maximumAmount = 10; + const assessmentMethod = "exclusive"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: feeCollectorAccountId, + feeCollectorsExempt: feeCollectorsExempt, + fractionalFee: { + numerator: numerator, + denominator: denominator, + minimumAmount: minimumAmount, + maximumAmount: maximumAmount, + assessmentMethod: assessmentMethod + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); + }); + + it("(#87) Creates a fungible token with a royalty fee", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + royaltyFee: { + numerator: 1, + denominator: 10, + fallbackFee: { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + amount: 10 + } + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_ROYALTY_FEE_ONLY_ALLOWED_FOR_NON_FUNGIBLE_UNIQUE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#88) Creates an NFT with a fractional fee", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + supplyKey: key, + tokenType: "nft", + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fractionalFee: { + numerator: 1, + denominator: 10, + minimumAmount: 1, + maximumAmount: 10, + assessmentMethod: "inclusive" + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FRACTIONAL_FEE_ONLY_ALLOWED_FOR_FUNGIBLE_COMMON"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#89) Creates a token with more than the maximum amount of fees allowed", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + customFees: [ + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + }, + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + }, + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + }, + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + }, + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + }, + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + }, + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + }, + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + }, + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + }, + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + }, + { + feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, + feeCollectorsExempt: false, + fixedFee: { + amount: 10 + } + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "CUSTOM_FEES_LIST_TOO_LONG"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Pause Key", function () { + async function verifyTokenCreationWithPauseKey(tokenId, pauseKey) { + expect(pauseKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).pauseKey.toStringDer()); + expect(pauseKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].pause_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: keyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithPauseKey(response.tokenId, keyList); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: nestedKeyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithPauseKey(response.tokenId, nestedKeyList); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: thresholdKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithPauseKey(response.tokenId, thresholdKey); + }); + + it("(#8) Creates a token with an invalid key as its pause key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + pauseKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Metadata", function () { + async function verifyTokenCreationWithMetadata(tokenId, metadata) { + expect(metadata).to.equal(await consensusInfoClient.getTokenInfo(tokenId).metadata); + expect(metadata).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].metadata); + } + + it("(#1) Creates a token with metadata", async function () { + const metadata = "1234"; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + metadata: metadata + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMetadata(response.tokenId, metadata); + }); + + it("(#2) Creates a token with empty metadata", async function () { + const metadata = ""; + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + metadata: metadata + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMetadata(response.tokenId, metadata); + }); + }); + + describe("Metadata Key", function () { + async function verifyTokenCreationWithMetadataKey(tokenId, metadataKey) { + expect(metadataKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).metadataKey.toStringDer()); + expect(metadataKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].metadata_key); + } + + it("(#1) Creates a token with a valid ED25519 public key as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: publicKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#3) Creates a token with a valid ED25519 private key as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: privateKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "ed25519PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + }, + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const keyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: keyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMetadataKey(response.tokenId, keyList.key); + }); + + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [ + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ecdsaSecp256k1PrivateKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }, + { + type: "keyList", + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + } + ] + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const nestedKeyList = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: nestedKeyList + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMetadataKey(response.tokenId, nestedKeyList.key); + }); + + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "thresholdKey", + threshold: 2, + keys: [ + { + type: "ed25519PrivateKey" + }, + { + type: "ecdsaSecp256k1PublicKey" + }, + { + type: "ed25519PublicKey" + } + ] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const thresholdKey = response.key; + + response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: thresholdKey + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenCreationWithMetadataKey(response.tokenId, thresholdKey.key); + }); + + it("(#8) Creates a token with an invalid key as its metadata key", async function () { + try { + const response = await JSONRPCRequest("createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + metadataKey: crypto.randomBytes(88).toString("hex") + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + return Promise.resolve(); +}); From ce7a67537a28c02d12572430b7dcd1daa62412fb Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Mon, 9 Sep 2024 12:49:29 -0400 Subject: [PATCH 16/25] feat: add name tests Signed-off-by: Rob Walworth --- .../test_tokenUpdateTransaction.js | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js index a084c43..7d37857 100644 --- a/test/token-service/test_tokenUpdateTransaction.js +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -211,11 +211,11 @@ describe("TokenCreateTransaction", function () { expect(name).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].name); } - it("(#1) Updates an immutable token with a symbol", async function () { + it("(#1) Updates an immutable token with a name", async function () { try { const response = await JSONRPCRequest("createToken", { tokenId: immutableTokenId, - symbol: "t" + name: "t" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -226,11 +226,11 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a symbol that is the minimum length", async function () { - const symbol = "t"; + it("(#2) Updates a mutable token with a name that is the minimum length", async function () { + const name = "t"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - symbol: symbol, + name: name, commonTransactionParams: { signers: [ mutableTokenAdminKey @@ -239,30 +239,30 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenSymbolUpdate(response.tokenId, symbol); + verifyTokenNameUpdate(response.tokenId, name); }); - it("(#3) Updates a mutable token with a symbol that is empty", async function () { - const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, - symbol: "", - commonTransactionParams: { - signers: [ - mutableTokenAdminKey - ] - } - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + it("(#3) Updates a mutable token with a name that is empty", async function () { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + name: "", + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); - // Symbol shouldn't change and should still remain as "testsymbol". - verifyTokenSymbolUpdate(response.tokenId, "testsymbol"); + // Name shouldn't change and should still remain as "testname". + verifyTokenNameUpdate(response.tokenId, "testname"); }); - it("(#4) Updates a mutable token with a symbol that is the maximum length", async function () { - const symbol = "This is a really long symbol but it is still valid because it is 100 characters exactly on the money" + it("(#4) Updates a mutable token with a name that is the maximum length", async function () { + const name = "This is a really long name but it is still valid because it is 100 characters exactly on the money!!" const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - symbol: symbol, + name: name, commonTransactionParams: { signers: [ mutableTokenAdminKey @@ -271,14 +271,14 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenSymbolUpdate(response.tokenId, symbol); + verifyTokenNameUpdate(response.tokenId, name); }); - it("(#5) Updates a mutable token with a symbol that exceeds the maximum length", async function () { + it("(#5) Updates a mutable token with a name that exceeds the maximum length", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - symbol: "This is a long symbol that is not valid because it exceeds 100 characters and it should fail the test", + name: "This is a long name that is not valid because it exceeds 100 characters and it should fail the test!!", commonTransactionParams: { signers: [ mutableTokenAdminKey @@ -287,18 +287,18 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "TOKEN_SYMBOL_TOO_LONG"); + assert.equal(err.data.status, "TOKEN_NAME_TOO_LONG"); return; } assert.fail("Should throw an error"); }); - it("(#6) Updates a mutable token with a valid symbol without signing with the token's admin key", async function () { + it("(#6) Updates a mutable token with a valid name without signing with the token's admin key", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - symbol: "t" + name: "t" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { From cffd5a7b8fc5cc6c43eb79bd24cba15f1a03d172 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Mon, 9 Sep 2024 13:22:05 -0400 Subject: [PATCH 17/25] feat: add treasury account ID tests Signed-off-by: Rob Walworth --- .../test_tokenUpdateTransaction.js | 556 ++++-------------- 1 file changed, 99 insertions(+), 457 deletions(-) diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js index 7d37857..1bee543 100644 --- a/test/token-service/test_tokenUpdateTransaction.js +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -17,6 +17,12 @@ describe("TokenCreateTransaction", function () { // Tests should not take longer than 30 seconds to fully execute. this.timeout(30000); + // Initial token parameters. + const initialTokenName = "testname"; + const initialTokenSymbol = "testsymbol"; + const initialTreasuryAccountId = process.env.OPERATOR_ACCOUNT_ID; + const initialSupply = 1000000; + // Two tokens should be created. One immutable token (no admin key) and another mutable. let immutableTokenId, mutableTokenId, mutableTokenAdminKey; @@ -25,10 +31,10 @@ describe("TokenCreateTransaction", function () { setOperator(process.env.OPERATOR_ACCOUNT_ID, process.env.OPERATOR_ACCOUNT_PRIVATE_KEY); let response = JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - initialSupply: 1000000, + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + initialSupply: initialSupply, tokenType: "ft" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -45,11 +51,11 @@ describe("TokenCreateTransaction", function () { mutableTokenAdminKey = response.key; response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - admin: mutableTokenAdminKey, - initialSupply: 1000000, + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenAdminKey, + initialSupply: initialSupply, tokenType: "ft" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -149,8 +155,8 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - // Symbol shouldn't change and should still remain as "testsymbol". - verifyTokenSymbolUpdate(response.tokenId, "testsymbol"); + // Symbol shouldn't change and should still remain as its initial value. + verifyTokenSymbolUpdate(response.tokenId, initialTokenSymbol); }); it("(#4) Updates a mutable token with a symbol that is the maximum length", async function () { @@ -254,8 +260,8 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - // Name shouldn't change and should still remain as "testname". - verifyTokenNameUpdate(response.tokenId, "testname"); + // Name shouldn't change and should still remain as its initial value. + verifyTokenNameUpdate(response.tokenId, initialTokenName); }); it("(#4) Updates a mutable token with a name that is the maximum length", async function () { @@ -310,550 +316,186 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Decimals", function () { - async function verifyTokenCreationWithDecimals(tokenId, decimals) { - expect(decimals).to.equal(await consensusInfoClient.getTokenInfo(tokenId).decimals); - expect(decimals).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].decimals); - } - - it("(#1) Creates a fungible token with 0 decimals", async function () { - const decimals = 0; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: decimals, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithDecimals(response.tokenId, decimals); - }); - - it("(#2) Creates a fungible token with -1 decimals", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: -1, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#3) Creates a fungible token with 2,147,483,647 (int32 max) decimals", async function () { - const decimals = 2147483647; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: decimals, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithDecimals(response.tokenId, decimals); - }); - - it("(#4) Creates a fungible token with 2,147,483,646 (int32 max - 1) decimals", async function () { - const decimals = 2147483646; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: decimals, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithDecimals(response.tokenId, decimals); - }); - - it("(#5) Creates a fungible token with 2,147,483,648 (int32 max + 1) decimals", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: 2147483648, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#6) Creates a fungible token with 4,294,967,295 (uint32 max) decimals", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: 4294967295, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#7) Creates a fungible token with 4,294,967,294 (uint32 max - 1) decimals", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: 4294967294, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#8) Creates a fungible token with -2,147,483,648 (int32 min) decimals", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: -2147483648, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#9) Creates a fungible token with -2,147,483,647 (int32 min + 1) decimals", async function () { + describe("Treasury Account ID", function () { + it("(#1) Updates an immutable token with a treasury account", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: -2147483647, + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } assert.fail("Should throw an error"); }); - it("(#10) Creates an NFT with a decimal amount of zero", async function () { + it("(#2) Updates a mutable token with a treasury account", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ed25519PrivateKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - const decimals = 0; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: decimals, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithDecimals(response.tokenId, decimals); - }); - - it("(#11) Creates an NFT with a nonzero decimal amount", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: 3, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - tokenType: "nft" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); - return; - } - - assert.fail("Should throw an error"); - }); - }); - - describe("Initial Supply", function () { - async function verifyTokenCreationWithInitialSupply(tokenId, initialSupply) { - expect(initialSupply).to.equal(await consensusInfoClient.getTokenInfo(tokenId).totalSupply); - expect(initialSupply).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].initial_supply); - } - - it("(#1) Creates a fungible token with 0 initial supply", async function () { - const initialSupply = 0; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: initialSupply, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); - }); - - it("(#2) Creates a fungible token with -1 initial supply", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: -1, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#3) Creates a fungible token with 9,223,372,036,854,775,807 (int64 max) initial supply", async function () { - const initialSupply = 9223372036854775807n; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: initialSupply, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + response = await JSONRPCRequest("createAccount", { + key: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; - verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); - }); - - it("(#4) Creates a fungible token with 9,223,372,036,854,775,806 (int64 max - 1) initial supply", async function () { - const initialSupply = 9223372036854775806n; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: initialSupply, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + treasuryAccountId: accountId, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + key + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); - }); - - it("(#5) Creates a fungible token with 9,223,372,036,854,775,808 (int64 max + 1) initial supply", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: 9223372036854775808n, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#6) Creates a fungible token with 18,446,744,073,709,551,615 (uint64 max) initial supply", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: 18446744073709551615n, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); - return; - } + expect(accountId).to.equal(await consensusInfoClient.getTokenInfo(tokenId).treasuryAccountId.toString()); + expect(accountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].treasury_account_id); - assert.fail("Should throw an error"); - }); + // Make sure the tokens were transferred from the initial treasury account to the new treasury account. + const initialTreasuryAccountBalance = await consensusInfoClient.getBalance(process.env.OPERATOR_ACCOUNT_ID); + const newTreasuryAccountBalance = await consensusInfoClient.getBalance(accountId); - it("(#7) Creates a fungible token with 18,446,744,073,709,551,614 (uint64 max - 1) initial supply", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: 18446744073709551614n, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); - return; - } + assert(initialTreasuryAccountBalance.tokens.has(mutableTokenId)).is.true; + assert(newTreasuryAccountBalance.tokens.has(mutableTokenId)).is.true; - assert.fail("Should throw an error"); + expect(initialTreasuryAccountBalance.tokens.get(mutableTokenId).size).to.equal(0); + expect(newTreasuryAccountBalance.tokens.get(mutableTokenId).size).to.equal(initialSupply); }); - it("(#8) Creates a fungible token with -9,223,372,036,854,775,808 (int64 min) initial supply", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: -9223372036854775808n, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#9) Creates a fungible token with -9,223,372,036,854,775,807 (int64 min + 1) initial supply", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: -9223372036854775807n, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#10) Creates a fungible token with a valid initial supply and decimals", async function () { - const decimals = 2; - const initialSupply = 1000000; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: decimals, - initialSupply: initialSupply, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply / (10 ** decimals)); - }); - - it("(#11) Creates a fungible token with a valid initial supply and more decimals", async function () { - const decimals = 6; - const initialSupply = 1000000; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - decimals: decimals, - initialSupply: initialSupply, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply / (10 ** decimals)); - }); - - it("(#12) Creates an NFT with an initial supply of zero", async function () { + it("(#3) Updates a mutable token with a treasury account without signing with the account's private key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - - const initialSupply = 0; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: initialSupply, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft" + + response = await JSONRPCRequest("createAccount", { + key: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithInitialSupply(response.tokenId, initialSupply); - }); + const accountId = response.accountId; - it("(#13) Creates an NFT with an initial supply of zero without a supply key", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: 0, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - tokenType: "nft" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenAdminKey, + treasuryAccountId: accountId, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); + assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } - + assert.fail("Should throw an error"); }); - it("(#14) Creates an NFT with a nonzero initial supply", async function () { + it("(#4) Updates a mutable token with a treasury account that doesn't exist", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - initialSupply: 3, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - tokenType: "nft" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + treasuryAccountId: "123.456.789", + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); + assert.equal(err.data.status, "INVALID_ACCOUNT_ID"); return; } assert.fail("Should throw an error"); }); - }); - - describe("Treasury Account", function () { - async function verifyTokenCreationWithTreasuryAccount(tokenId, treasuryAccountId) { - expect(treasuryAccountId).to.equal(await consensusInfoClient.getTokenInfo(tokenId).treasuryAccountId.toString()); - expect(treasuryAccountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].treasury_account_id); - } - it("(#1) Creates a token with a treasury account", async function () { + it("(#5) Updates a mutable token with a treasury account that is deleted", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - + response = await JSONRPCRequest("createAccount", { key: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const accountId = response.accountId; - - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: accountId, + + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, commonTransactionParams: { - signers: [ - key - ] + signers: [ + key + ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithTreasuryAccount(response.tokenId, accountId); - }); - - it("(#2) Creates a token with a treasury account without signing with the account's private key", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - response = await JSONRPCRequest("createAccount", { - key: key, - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const accountId = response.accountId; - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: accountId - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); - return; - } - - // The test failed, no error was thrown. - assert.fail("Should throw an error"); - }); - - it("(#3) Creates a token with a treasury account that doesn't exist", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: "123.456.789" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenAdminKey, + treasuryAccountId: accountId, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + key + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_ACCOUNT_ID"); + assert.equal(err.data.status, "ACCOUNT_DELETED"); return; } - - // The test failed, no error was thrown. + assert.fail("Should throw an error"); }); - it("(#4) Creates a token with a treasury account that is deleted", async function () { + it("(#6) Updates a mutable token with a treasury account without signing with the token's admin key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - + response = await JSONRPCRequest("createAccount", { key: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const accountId = response.accountId; - response = await JSONRPCRequest("deleteAccount", { - deleteAccountId: accountId, - transferAccountId: process.env.OPERATOR_ACCOUNT_ID, - commonTransactionParams: { - signers: [ - key - ] - } - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenAdminKey, treasuryAccountId: accountId, commonTransactionParams: { signers: [ - key + key ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TREASURY_ACCOUNT_FOR_TOKEN"); + assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } - - // The test failed, no error was thrown. + assert.fail("Should throw an error"); }); }); From 7e4a56517e8b13147260720093f454211b01cb18 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Mon, 9 Sep 2024 17:29:17 -0400 Subject: [PATCH 18/25] feat: finish adding all tests Signed-off-by: Rob Walworth --- .../test_tokenUpdateTransaction.js | 6009 +++++------------ 1 file changed, 1829 insertions(+), 4180 deletions(-) diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js index 1bee543..df1781f 100644 --- a/test/token-service/test_tokenUpdateTransaction.js +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -486,7 +486,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: accountId, commonTransactionParams: { signers: [ - key + key ] } }); @@ -501,12 +501,33 @@ describe("TokenCreateTransaction", function () { }); describe("Admin Key", function () { - async function verifyTokenCreationWithAdminKey(tokenId, adminKey) { + async function verifyTokenAdminKeyUpdate(tokenId, adminKey) { expect(adminKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).adminKey.toStringDer()); expect(adminKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].admin_key); } - it("(#1) Creates a token with a valid ED25519 public key as its admin key", async function () { + it("(#1) Updates an immutable token with a valid key as its admin key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + adminKey: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Updates a mutable token with a valid ED25519 public key as its admin key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -519,13 +540,12 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, adminKey: publicKey, commonTransactionParams: { signers: [ + mutableTokenAdminKey, privateKey ] } @@ -533,10 +553,10 @@ describe("TokenCreateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenAdminKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its admin key", async function () { + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its admin key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); @@ -549,13 +569,12 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, adminKey: publicKey, commonTransactionParams: { signers: [ + mutableTokenAdminKey, privateKey ] } @@ -563,10 +582,10 @@ describe("TokenCreateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenAdminKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#3) Creates a token with a valid ED25519 private key as its admin key", async function () { + it("(#4) Updates a mutable token with a valid ED25519 private key as its admin key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -579,13 +598,12 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, adminKey: privateKey, commonTransactionParams: { signers: [ + mutableTokenAdminKey, privateKey ] } @@ -593,10 +611,10 @@ describe("TokenCreateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenAdminKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its admin key", async function () { + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its admin key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); @@ -609,10 +627,8 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, adminKey: privateKey, commonTransactionParams: { signers: [ @@ -623,10 +639,10 @@ describe("TokenCreateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithAdminKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenAdminKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { const keyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ @@ -646,13 +662,12 @@ describe("TokenCreateTransaction", function () { }); if (keyList.status === "NOT_IMPLEMENTED") this.skip(); - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, adminKey: keyList.key, commonTransactionParams: { signers: [ + mutableTokenAdminKey, keyList.privateKeys[0], keyList.privateKeys[1], keyList.privateKeys[2], @@ -662,10 +677,10 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithAdminKey(response.tokenId, keyList.key); + verifyTokenAdminKeyUpdate(response.tokenId, keyList.key); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its admin key", async function () { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its admin key", async function () { const nestedKeyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ @@ -706,13 +721,12 @@ describe("TokenCreateTransaction", function () { }); if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, adminKey: nestedKeyList.key, commonTransactionParams: { signers: [ + mutableTokenAdminKey, nestedKeyList.privateKeys[0], nestedKeyList.privateKeys[1], nestedKeyList.privateKeys[2], @@ -724,10 +738,10 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithAdminKey(response.tokenId, nestedKeyList.key); + verifyTokenAdminKeyUpdate(response.tokenId, nestedKeyList.key); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { const thresholdKey = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, @@ -745,10 +759,8 @@ describe("TokenCreateTransaction", function () { }); if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, adminKey: thresholdKey.key, commonTransactionParams: { signers: [ @@ -759,10 +771,10 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithAdminKey(response.tokenId, thresholdKey.key); + verifyTokenAdminKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#8) Creates a token with a valid key as its admin key but doesn't sign with it", async function () { + it("(#9) Updates a mutable token with a valid key as its admin key but doesn't sign with it", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); @@ -770,11 +782,14 @@ describe("TokenCreateTransaction", function () { const key = response.key; try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - adminKey: key + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + adminKey: key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -785,13 +800,16 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#9) Creates a token with an invalid key as its admin key", async function () { + it("(#10) Updates a mutable token with an invalid key as its admin key", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - adminKey: crypto.randomBytes(88).toString("hex") + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + adminKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -804,48 +822,91 @@ describe("TokenCreateTransaction", function () { }); describe("KYC Key", function () { - async function verifyTokenCreationWithKycKey(tokenId, kycKey) { + async function verifyTokenKycKeyUpdate(tokenId, kycKey) { expect(kycKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).kycKey.toStringDer()); expect(kycKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].kyc_key); } - it("(#1) Creates a token with a valid ED25519 public key as its KYC key", async function () { + it("(#1) Updates an immutable token with a valid key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey" }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + kycKey: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Updates a mutable token with a valid ED25519 public key as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: publicKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + kycKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenKycKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its KYC key", async function () { + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: publicKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + kycKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenKycKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#3) Creates a token with a valid ED25519 private key as its KYC key", async function () { + it("(#4) Updates a mutable token with a valid ED25519 private key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -858,19 +919,23 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + kycKey: privateKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenKycKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its KYC key", async function () { + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); @@ -883,20 +948,23 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + kycKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithKycKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenKycKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { + const keyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -913,22 +981,28 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const keyList = response.key; + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: keyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + kycKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithKycKey(response.tokenId, keyList); + verifyTokenKycKeyUpdate(response.tokenId, keyList.key); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its KYC key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its KYC key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -966,22 +1040,30 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const nestedKeyList = response.key; + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: nestedKeyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + kycKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithKycKey(response.tokenId, nestedKeyList); + verifyTokenKycKeyUpdate(response.tokenId, nestedKeyList.key); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -996,27 +1078,59 @@ describe("TokenCreateTransaction", function () { } ] }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + kycKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const thresholdKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: thresholdKey + verifyTokenKycKeyUpdate(response.tokenId, thresholdKey.key); + }); + + it("(#9) Updates a mutable token with a valid key as its KYC key but doesn't sign with it", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + kycKey: key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } - verifyTokenCreationWithKycKey(response.tokenId, thresholdKey); + assert.fail("Should throw an error"); }); - it("(#8) Creates a token with an invalid key as its KYC key", async function () { + it("(#10) Updates a mutable token with an invalid key as its KYC key", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - kycKey: crypto.randomBytes(88).toString("hex") + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + kycKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1024,54 +1138,96 @@ describe("TokenCreateTransaction", function () { return; } - // The test failed, no error was thrown. assert.fail("Should throw an error"); }); }); describe("Freeze Key", function () { - async function verifyTokenCreationWithFreezeKey(tokenId, freezeKey) { + async function verifyTokenFreezeKeyUpdate(tokenId, freezeKey) { expect(freezeKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).freezeKey.toStringDer()); expect(freezeKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].freeze_key); } - it("(#1) Creates a token with a valid ED25519 public key as its freeze key", async function () { + it("(#1) Updates an immutable token with a valid key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey" }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + freezeKey: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Updates a mutable token with a valid ED25519 public key as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: publicKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + freezeKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenFreezeKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its freeze key", async function () { + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: publicKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + freezeKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenFreezeKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#3) Creates a token with a valid ED25519 private key as its freeze key", async function () { + it("(#4) Updates a mutable token with a valid ED25519 private key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -1084,19 +1240,23 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + freezeKey: privateKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenFreezeKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its freeze key", async function () { + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); @@ -1109,20 +1269,23 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: privateKey - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + freezeKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithFreezeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenFreezeKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { + const keyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1139,22 +1302,28 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const keyList = response.key; + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: keyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + freezeKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFreezeKey(response.tokenId, keyList); + verifyTokenFreezeKeyUpdate(response.tokenId, keyList.key); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its freeze key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its freeze key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1192,22 +1361,30 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const nestedKeyList = response.key; + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: nestedKeyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + freezeKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFreezeKey(response.tokenId, nestedKeyList); + verifyTokenFreezeKeyUpdate(response.tokenId, nestedKeyList.key); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -1222,27 +1399,59 @@ describe("TokenCreateTransaction", function () { } ] }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + freezeKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const thresholdKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: thresholdKey + verifyTokenFreezeKeyUpdate(response.tokenId, thresholdKey.key); + }); + + it("(#9) Updates a mutable token with a valid key as its freeze key but doesn't sign with it", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + freezeKey: key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } - verifyTokenCreationWithFreezeKey(response.tokenId, thresholdKey); + assert.fail("Should throw an error"); }); - it("(#8) Creates a token with an invalid key as its freeze key", async function () { + it("(#10) Updates a mutable token with an invalid key as its freeze key", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: crypto.randomBytes(88).toString("hex") + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + freezeKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1255,48 +1464,91 @@ describe("TokenCreateTransaction", function () { }); describe("Wipe Key", function () { - async function verifyTokenCreationWithWipeKey(tokenId, wipeKey) { + async function verifyTokenWipeKeyUpdate(tokenId, wipeKey) { expect(wipeKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).wipeKey.toStringDer()); expect(wipeKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].wipe_key); } - it("(#1) Creates a token with a valid ED25519 public key as its wipe key", async function () { + it("(#1) Updates an immutable token with a valid key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey" }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + wipeKey: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Updates a mutable token with a valid ED25519 public key as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: publicKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + wipeKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenWipeKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its wipe key", async function () { + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: publicKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + wipeKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenWipeKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#3) Creates a token with a valid ED25519 private key as its wipe key", async function () { + it("(#4) Updates a mutable token with a valid ED25519 private key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -1309,19 +1561,23 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + wipeKey: privateKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenWipeKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its wipe key", async function () { + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); @@ -1334,20 +1590,23 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + wipeKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithWipeKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenWipeKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { + const keyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1364,22 +1623,28 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const keyList = response.key; + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: keyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + wipeKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithWipeKey(response.tokenId, keyList); + verifyTokenWipeKeyUpdate(response.tokenId, keyList.key); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its wipe key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its wipe key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1417,22 +1682,30 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const nestedKeyList = response.key; + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: nestedKeyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + wipeKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithWipeKey(response.tokenId, nestedKeyList); + verifyTokenWipeKeyUpdate(response.tokenId, nestedKeyList.key); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -1447,27 +1720,59 @@ describe("TokenCreateTransaction", function () { } ] }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + wipeKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const thresholdKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: thresholdKey + verifyTokenWipeKeyUpdate(response.tokenId, thresholdKey.key); + }); + + it("(#9) Updates a mutable token with a valid key as its wipe key but doesn't sign with it", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + wipeKey: key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } - verifyTokenCreationWithWipeKey(response.tokenId, thresholdKey); + assert.fail("Should throw an error"); }); - it("(#8) Creates a token with an invalid key as its wipe key", async function () { + it("(#10) Updates a mutable token with an invalid key as its wipe key", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - wipeKey: crypto.randomBytes(88).toString("hex") + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + wipeKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1480,48 +1785,33 @@ describe("TokenCreateTransaction", function () { }); describe("Supply Key", function () { - async function verifyTokenCreationWithSupplyKey(tokenId, supplyKey) { + async function verifyTokenSupplyKeyUpdate(tokenId, supplyKey) { expect(supplyKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).supplyKey.toStringDer()); expect(supplyKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].supply_key); } - it("(#1) Creates a token with a valid ED25519 public key as its supply key", async function () { + it("(#1) Updates an immutable token with a valid key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey" }); - const publicKey = response.key; - - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: publicKey - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); - }); - - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its supply key", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" - }); - const publicKey = response.key; - - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: publicKey - }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; - // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + supplyKey: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); }); - it("(#3) Creates a token with a valid ED25519 private key as its supply key", async function () { + it("(#2) Updates a mutable token with a valid ED25519 public key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -1534,19 +1824,23 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + supplyKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenSupplyKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its supply key", async function () { + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); @@ -1559,20 +1853,81 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + supplyKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithSupplyKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenSupplyKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#4) Updates a mutable token with a valid ED25519 private key as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + supplyKey: privateKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenSupplyKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + supplyKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenSupplyKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { + const keyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1589,22 +1944,28 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const keyList = response.key; + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: keyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + supplyKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithSupplyKey(response.tokenId, keyList); + verifyTokenSupplyKeyUpdate(response.tokenId, keyList.key); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its supply key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its supply key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -1642,22 +2003,30 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const nestedKeyList = response.key; + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: nestedKeyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + supplyKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithSupplyKey(response.tokenId, nestedKeyList); + verifyTokenSupplyKeyUpdate(response.tokenId, nestedKeyList.key); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -1672,27 +2041,59 @@ describe("TokenCreateTransaction", function () { } ] }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + supplyKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const thresholdKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: thresholdKey + verifyTokenSupplyKeyUpdate(response.tokenId, thresholdKey.key); + }); + + it("(#9) Updates a mutable token with a valid key as its supply key but doesn't sign with it", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + supplyKey: key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } - verifyTokenCreationWithSupplyKey(response.tokenId, thresholdKey.key); + assert.fail("Should throw an error"); }); - it("(#8) Creates a token with an invalid key as its supply key", async function () { + it("(#10) Updates a mutable token with an invalid key as its supply key", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: crypto.randomBytes(88).toString("hex") + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + supplyKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1704,644 +2105,481 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Freeze Default", function () { - async function verifyTokenCreationWithFreezeDefault(tokenId, freezeDefault) { - expect(freezeDefault).to.equal(await consensusInfoClient.getTokenInfo(tokenId).freezeDefault); - expect(freezeDefault).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].freeze_default); - } + describe("Auto Renew Account", function () { + it("(#1) Updates an immutable token with an auto renew account", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + autoRenewAccountId: process.env.OPERATOR_ACCOUNT_ID + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); + }); - it("(#1) Creates a token with a frozen default status", async function () { + it("(#2) Updates a mutable token with an auto renew account", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - const freezeDefault = true; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeKey: key, - freezeDefault: freezeDefault + response = await JSONRPCRequest("createAccount", { + key: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; - verifyTokenCreationWithFreezeDefault(response.tokenId, freezeDefault); - }); - - it("(#2) Creates a token with a frozen default status and no freeze key", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeDefault: true - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "TOKEN_HAS_NO_FREEZE_KEY"); - return; - } + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); - assert.fail("Should throw an error"); + const tokenId = response.tokenId; + expect(accountId).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewAccountId.toString()); + expect(accountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_account); }); - it("(#3) Creates a token with an unfrozen default status", async function () { - const freezeDefault = false; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - freezeDefault: freezeDefault + it("(#3) Updates a mutable token with an auto renew account without signing with the account's private key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; - verifyTokenCreationWithFreezeDefault(response.tokenId, freezeDefault); - }); - }); - - describe("Expiration Time", function () { - async function verifyTokenCreationWithExpirationTime(tokenId, expirationTime) { - expect(expirationTime).to.equal(await consensusInfoClient.getTokenInfo(tokenId).expirationTime); - expect(expirationTime).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].expiry_timestamp); - } + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; - it("(#1) Creates a token with an expiration time of 0 seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: 0 + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } assert.fail("Should throw an error"); }); - it("(#2) Creates a token with an expiration time of -1 seconds", async function () { + it("(#4) Updates a mutable token with an auto renew account that doesn't exist", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: -1 + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewAccountId: "123.456.789", + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); return; } assert.fail("Should throw an error"); }); - it("(#3) Creates a token with an expiration time of 9,223,372,036,854,775,807 (int64 max) seconds", async function () { + it("(#5) Updates a mutable token with an empty auto renew account", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: 9223372036854775807n + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewAccountId: "", + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + assert.equal(err.code, -32603, "Internal error"); return; } assert.fail("Should throw an error"); }); - it("(#4) Creates a token with an expiration time of 9,223,372,036,854,775,806 (int64 max - 1) seconds", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: 9223372036854775806n - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); - return; - } - - assert.fail("Should throw an error"); - }); + it("(#6) Updates a mutable token with an auto renew account that is deleted", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; - it("(#5) Creates a token with an expiration time of 9,223,372,036,854,775,808 (int64 max + 1) seconds", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: 9223372036854775808n - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); - return; - } + response = await JSONRPCRequest("createAccount", { + key: key, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; - assert.fail("Should throw an error"); - }); + response = await JSONRPCRequest("deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [ + key + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); - it("(#6) Creates a token with an expiration time of 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: 18446744073709551615n + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + key + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); return; } assert.fail("Should throw an error"); }); - it("(#7) Creates a token with an expiration time of 18,446,744,073,709,551,614 (uint64 max - 1) seconds", async function () { + it("(#7) Updates a mutable token with an auto renew account without signing with the token's admin key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("createAccount", { + key: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const accountId = response.accountId; + try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: 18446744073709551614n + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenAdminKey, + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [ + key + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } - + assert.fail("Should throw an error"); }); + }); - it("(#8) Creates a token with an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + describe("Auto Renew Period", function () { + async function verifyTokenAutoRenewPeriodUpdate(tokenId, autoRenewPeriod) { + expect(autoRenewPeriod).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewPeriod); + expect(autoRenewPeriod).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_period); + } + + it("(#1) Updates an immutable token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: -9223372036854775808n + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + autoRenewPeriod: 5184000 }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } assert.fail("Should throw an error"); }); - it("(#9) Creates a token with an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { + it("(#2) Updates a mutable token with an auto renew period set to 0 seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: -9223372036854775807n + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: 0, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); - it("(#10) Creates a token with an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { - const expirationTime = parseInt((Date.now() / 1000) + 5184000); - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: expirationTime - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithExpirationTime(response.tokenId, expirationTime); - }); - - it("(#11) Creates a token with an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { - const expirationTime = parseInt((Date.now() / 1000) + 2592000); - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: expirationTime - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithExpirationTime(response.tokenId, expirationTime); - }); - - //it("(#12) Creates a token with an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { - // try { - // const response = await JSONRPCRequest("createToken", { - // name: "testname", - // symbol: "testsymbol", - // treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - // expirationTime: (Date.now() / 1000) + 2591999 - // }); - // if (response.status === "NOT_IMPLEMENTED") this.skip(); - // } catch (err) { - // assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); - // return; - // } - // - // assert.fail("Should throw an error"); - //}); - - it("(#13) Creates a token with an expiration time of 8,000,001 seconds from the current time", async function () { - const expirationTime = parseInt((Date.now() / 1000) + 8000001); - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: expirationTime - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithExpirationTime(response.tokenId, expirationTime); - }); - - it("(#14) Creates a token with an expiration time of 8,000,002 seconds from the current time", async function () { + it("(#3) Updates a mutable token with an auto renew period set to -1 seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: (Date.now() / 1000) + 8000002 + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: -1, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); - }); - - describe("Auto Renew Account", function () { - it ("(#1) Creates a token with an auto renew account", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - response = await JSONRPCRequest("createAccount", { - key: key, - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const accountId = response.accountId; - - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewAccountId: accountId, - commonTransactionParams: { - signers: [ - key - ] - } - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const tokenId = response.tokenId; - - expect(accountId).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewAccountId.toString()); - expect(accountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_account); - }); - - it ("(#2) Creates a token with an auto renew account without signing with the account's key", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - response = await JSONRPCRequest("createAccount", { - key: key, - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const accountId = response.accountId; + it("(#4) Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,807 (int64 max) seconds", async function () { try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewAccountId: accountId + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: 9223372036854775807n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); - it ("(#3) Creates a token with an auto renew account that doesn't exist", async function () { + it("(#5) Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,806 (int64 max - 1) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewAccountId: "123.456.789" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: 9223372036854775806n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); - it ("(#4) Creates a token with an empty auto renew account", async function () { + it("(#6) Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,808 (int64 max + 1) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewAccountId: "" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: 9223372036854775808n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code, -32603, "Internal error"); + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - - // The test failed, no error was thrown. + assert.fail("Should throw an error"); }); - it ("(#5) Creates a token with an auto renew account that is deleted", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - response = await JSONRPCRequest("createAccount", { - key: key, - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const accountId = response.accountId; - - response = await JSONRPCRequest("deleteAccount", { - deleteAccountId: accountId, - transferAccountId: process.env.OPERATOR_ACCOUNT_ID, - commonTransactionParams: { - signers: [ - key - ] - } - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - + it("(#7) Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewAccountId: accountId, + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: 18446744073709551615n, commonTransactionParams: { signers: [ - key + mutableTokenAdminKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - - // The test failed, no error was thrown. + assert.fail("Should throw an error"); }); - }); - - describe("Auto Renew Period", function () { - async function verifyTokenCreationWithAutoRenewPeriod(tokenId, autoRenewPeriod) { - expect(autoRenewPeriod).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewPeriod); - expect(autoRenewPeriod).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_period); - } - - it ("(#1) Creates a token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { - const autoRenewPeriod = 5184000 - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewPeriod: autoRenewPeriod - }); - - verifyTokenCreationWithAutoRenewPeriod(response.tokenId, autoRenewPeriod); - }); - it ("(#2) Creates a token with an auto renew period set to -1 seconds", async function () { + it("(#8) Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,614 (uint64 max - 1) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewPeriod: -1 + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: 18446744073709551614n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); - it ("(#3) Creates a token with an auto renew period set to the minimum period of 30 days (2,592,000 seconds)", async function () { - const autoRenewPeriod = 2592000; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewPeriod: autoRenewPeriod - }); - - verifyTokenCreationWithAutoRenewPeriod(response.tokenId, autoRenewPeriod); - }); - - it ("(#4) Creates a token with an auto renew period set to the minimum period of 30 days minus one second (2,591,999 seconds)", async function () { + it("(#9) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,808 (int64 min) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewPeriod: 2591999 + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: -9223372036854775808n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); - it ("(#5) Creates a token with an auto renew period set to the maximum period of 8,000,001 seconds", async function () { - const autoRenewPeriod = 8000001; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewPeriod: autoRenewPeriod - }); - - verifyTokenCreationWithAutoRenewPeriod(response.tokenId, autoRenewPeriod); - }); - - it ("(#6) Creates a token with an auto renew period set to the maximum period plus one second (8,000,002 seconds)", async function () { + it("(#10) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - autoRenewPeriod: 8000002 + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: -9223372036854775807n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); - }); - - describe("Memo", function () { - async function verifyTokenCreationWithMemo(tokenId, memo) { - expect(memo).to.equal(await consensusInfoClient.getTokenInfo(tokenId).memo); - expect(memo).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].memo); - } - it ("(#1) Creates a token with a memo that is a valid length", async function () { - const memo = "testmemo" - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - memo: memo + it("(#11) Updates a mutable token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { + const autoRenewPeriod = 5184000; + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: autoRenewPeriod, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithMemo(response.tokenId, memo); + verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); }); - it ("(#2) Creates a token with a memo that is the minimum length", async function () { - const memo = "" - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - memo: memo + it("(#12) Updates a mutable token with an auto renew period set to 30 days (2,592,000 seconds)", async function () { + const autoRenewPeriod = 2592000; + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: autoRenewPeriod, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithMemo(response.tokenId, memo); - }); - - it ("(#3) Creates a token with a memo that is the maximum length", async function () { - const memo = "This is a really long memo but it is still valid because it is 100 characters exactly on the money!!" - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - memo: memo - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithMemo(response.tokenId, memo); + verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); }); - it ("(#4) Creates a token with a memo that exceeds the maximum length", async function () { + it("(#13) Updates a mutable token with an auto renew period set to 30 days minus one second (2,591,999 seconds)", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - memo: "This is a long memo that is not valid because it exceeds 100 characters and it should fail the test!!" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: 2591999, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "MEMO_TOO_LONG"); + assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); return; } assert.fail("Should throw an error"); }); - }); - - describe("Token Type", function () { - async function verifyTokenCreationWithTokenType(tokenId, type) { - expect(type).to.equal(await consensusInfoClient.getTokenInfo(tokenId).type); - expect(type).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].type); - } - - it ("(#1) Creates a fungible token", async function () { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - tokenType: "ft" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithTokenType(response.tokenId, "FUNGIBLE_COMMON"); - }); - it ("(#2) Creates an NFT", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" - });; - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft" + it("(#14) Updates a mutable token with an auto renew period set to 8,000,001 seconds", async function () { + const autoRenewPeriod = 8000001; + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: autoRenewPeriod, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithTokenType(response.tokenId, "NON_FUNGIBLE_UNIQUE"); + verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); }); - it ("(#3) Creates an NFT without a supply key", async function () { + it("(#15) Updates a mutable token with an auto renew period set to 8,000,002 seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - tokenType: "nft" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: 8000002, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); + assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); return; } @@ -2349,288 +2587,446 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Supply Type", function () { - async function verifyTokenCreationWithSupplyType(tokenId, type) { - expect(type).to.equal(await consensusInfoClient.getTokenInfo(tokenId).supplyType); - expect(type).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].supply_type); - } - - it ("(#1) Creates a token with a finite supply", async function () { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "finite", - maxSupply: 1000000 - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithSupplyType(response.tokenId, "FINITE"); - }) - - it ("(#2) Creates a token with an infinite supply", async function () { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "infinite" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithSupplyType(response.tokenId, "INFINITE"); - }) - }); - - describe("Max Supply", function () { - async function verifyTokenCreationWithMaxSupply(tokenId, maxSupply) { - expect(maxSupply).to.equal(await consensusInfoClient.getTokenInfo(tokenId).maxSupply); - expect(maxSupply).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].max_supply); + describe("Expiration Time", function () { + async function verifyTokenExpirationTimeUpdate(tokenId, expirationTime) { + expect(expirationTime).to.equal(await consensusInfoClient.getTokenInfo(tokenId).expirationTime); + expect(expirationTime).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].expiry_timestamp); } - - it("(#1) Creates a token with 0 max supply", async function () { + + it("(#1) Updates an immutable token with a valid expiration time", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "finite", - maxSupply: 0 + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + expirationTime: parseInt((Date.now() / 1000) + 5184000) }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } assert.fail("Should throw an error"); }); - it("(#2) Creates a token with -1 max supply", async function () { + it("(#2) Updates a mutable token to an expiration time of 0", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "finite", - maxSupply: -1 + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: 0, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } assert.fail("Should throw an error"); }); - it("(#3) Creates a token with 9,223,372,036,854,775,807 (int64 max) max supply", async function () { - const maxSupply = 9223372036854775807n; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "finite", - maxSupply: maxSupply - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + it("(#3) Updates a mutable token to an expiration time of -1", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: -1, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } - verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); + assert.fail("Should throw an error"); }); - it("(#4) Creates a token with 9,223,372,036,854,775,806 (int64 max - 1) max supply", async function () { - const maxSupply = 9223372036854775806n; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "finite", - maxSupply: maxSupply - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + it("(#4) Updates a mutable token to an expiration time of 9,223,372,036,854,775,807 (int64 max) seconds", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: 9223372036854775807n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } - verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); + assert.fail("Should throw an error"); }); - it("(#5) Creates a token with 9,223,372,036,854,775,808 (int64 max + 1) max supply", async function () { + it("(#5) Updates a mutable token to an expiration time of 9,223,372,036,854,775,806 (int64 max - 1) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "finite", - maxSupply: 9223372036854775808n + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: 9223372036854775806n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } assert.fail("Should throw an error"); }); - it("(#6) Creates a token with 18,446,744,073,709,551,615 (uint64 max) max supply", async function () { + it("(#6) Updates a mutable token to an expiration time of 9,223,372,036,854,775,808 (int64 max + 1) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "finite", - maxSupply: 18446744073709551615n + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: 9223372036854775808n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } assert.fail("Should throw an error"); }); - it("(#7) Creates a token with 18,446,744,073,709,551,614 (uint64 max) max supply", async function () { + it("(#7) Updates a mutable token to an expiration time of 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "finite", - maxSupply: 18446744073709551614n + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: 18446744073709551615n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } assert.fail("Should throw an error"); }); - it("(#8) Creates a token with -9,223,372,036,854,775,808 (int64 min) max supply", async function () { + it("(#8) Updates a mutable token to an expiration time of 18,446,744,073,709,551,614 (uint64 max - 1) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "finite", - maxSupply: -9223372036854775808n + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: 18446744073709551614n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } assert.fail("Should throw an error"); }); - it("(#9) Creates a token with -9,223,372,036,854,775,807 (int64 min) max supply", async function () { + it("(#9) Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "finite", - maxSupply: -9223372036854775807n + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: -9223372036854775808n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } assert.fail("Should throw an error"); }); - it("(#10) Creates a token with a max supply and an infinite supply type", async function () { + it("(#10) Updates a mutable token to an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyType: "infinite", - maxSupply: 1000000 + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: -9223372036854775807n, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } assert.fail("Should throw an error"); }); - }); - - describe("Fee Schedule Key", function () { - async function verifyTokenCreationWithFeeScheduleKey(tokenId, feeScheduleKey) { - expect(feeScheduleKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).feeScheduleKey.toStringDer()); - expect(feeScheduleKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].fee_schedule_key); - } - it("(#1) Creates a token with a valid ED25519 public key as its fee schedule key", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" - }); - const publicKey = response.key; - - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: publicKey + it("(#11) Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { + const expirationTime = parseInt((Date.now() / 1000) + 5184000); + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: expirationTime, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - - // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + + verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its fee schedule key", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" - }); - const publicKey = response.key; - - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: publicKey + it("(#12) Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { + const expirationTime = parseInt((Date.now() / 1000) + 2592000); + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: expirationTime, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + }); - // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + it("(#13) Creates a token with an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: parseInt((Date.now() / 1000) + 2591999), + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); }); - it("(#3) Creates a token with a valid ED25519 private key as its fee schedule key", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + it("(#14) Updates a mutable token with an expiration time 8,000,001 seconds from the current time", async function () { + const expirationTime = parseInt((Date.now() / 1000) + 8000001); + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: expirationTime, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey", - fromKey: privateKey - }); - const publicKey = response.key; + + verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + }); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: privateKey - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); + it("(#15) Updates a mutable token with an expiration time 8,000,002 seconds from the current time", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + expirationTime: 8000002, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } - // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + assert.fail("Should throw an error"); }); + }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its fee schedule key", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); + describe("Memo", function () { + async function verifyTokenMemoUpdate(tokenId, memo) { + expect(memo).to.equal(await consensusInfoClient.getTokenInfo(tokenId).memo); + expect(memo).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].memo); + } + + it("(#1) Updates an immutable token with a memo that is a valid length", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + memo: "testmemo" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Updates a mutable token with a memo that is a valid length", async function () { + const memo = "testmemo" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + memo: memo, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenMemoUpdate(response.tokenId, memo); + }); + + it("(#3) Updates a mutable token with a memo that is the minimum length", async function () { + const memo = "" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + memo: memo, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenMemoUpdate(response.tokenId, memo); + }); + + it("(#4) Updates a mutable token with a memo that is the minimum length", async function () { + const memo = "This is a really long memo but it is still valid because it is 100 characters exactly on the money!!" + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + memo: memo, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenMemoUpdate(response.tokenId, memo); + }); + + it("(#5) Updates a mutable token with a memo that exceeds the maximum length", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + memo: "This is a long memo that is not valid because it exceeds 100 characters and it should fail the test!!", + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "MEMO_TOO_LONG"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Fee Schedule Key", function () { + async function verifyTokenFeeScheduleKeyUpdate(tokenId, feeScheduleKey) { + expect(feeScheduleKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).feeScheduleKey.toStringDer()); + expect(feeScheduleKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].fee_schedule_key); + } + + it("(#1) Updates an immutable token with a valid key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + feeScheduleKey: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Updates a mutable token with a valid ED25519 public key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenFeeScheduleKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + }); + + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; @@ -2640,20 +3036,81 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithFeeScheduleKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenFeeScheduleKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#4) Updates a mutable token with a valid ED25519 private key as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: privateKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenFeeScheduleKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey + }); + const publicKey = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + verifyTokenFeeScheduleKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + }); + + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { + const keyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -2670,22 +3127,28 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const keyList = response.key; + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: keyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFeeScheduleKey(response.tokenId, keyList); + verifyTokenFeeScheduleKeyUpdate(response.tokenId, keyList.key); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its fee schedule key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its fee schedule key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -2723,22 +3186,30 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const nestedKeyList = response.key; + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: nestedKeyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFeeScheduleKey(response.tokenId, nestedKeyList); + verifyTokenFeeScheduleKeyUpdate(response.tokenId, nestedKeyList.key); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -2753,3148 +3224,156 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const thresholdKey = response.key; + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: thresholdKey + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFeeScheduleKey(response.tokenId, thresholdKey); + verifyTokenFeeScheduleKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#8) Creates a token with an invalid key as its fee schedule key", async function () { + it("(#9) Updates a mutable token with a valid key as its fee schedule key but doesn't sign with it", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeScheduleKey: crypto.randomBytes(88).toString("hex") + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.code, -32603, "Internal error"); + assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } assert.fail("Should throw an error"); }); - }); - - describe("Custom Fees", function () { - async function consensusNodeFeeEqualsCustomFee(customFee, feeCollectorAccountId, feeCollectorsExempt) { - return feeCollectorAccountId === customFee.feeCollectorAccountId.toString() && - feeCollectorsExempt === customFee.allCollectorsAreExempt; - } - - async function consensusNodeFeeEqualsCustomFixedFee(customFixedFee, feeCollectorAccountId, feeCollectorsExempt, amount) { - return consensusNodeFeeEqualsCustomFee(customFixedFee, feeCollectorAccountId, feeCollectorsExempt) && - amount === customFixedFee.amount; - } - - async function consensusNodeFeeEqualsCustomFractionalFee(customFractionalFee, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod) { - return consensusNodeFeeEqualsCustomFee(customFractionalFee, feeCollectorAccountId, feeCollectorsExempt) && - numerator === customFractionalFee.numerator && - denominator === customFractionalFee.denominator && - minAmount === customFractionalFee.minimumAmount && - maxAmount === customFractionalFee.maximumAmount && - assessmentMethod === customFractionalFee.assessmentMethod.toString().toLowerCase(); - } - - async function consensusNodeFeeEqualsCustomRoyaltyFee(customRoyaltyFee, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeAmount) { - return consensusNodeFeeEqualsCustomFee(customRoyaltyFee, feeCollectorAccountId, feeCollectorsExempt) && - numerator === customRoyaltyFee.numerator && - denominator === customRoyaltyFee.denominator && - fixedFeeAmount === customRoyaltyFee.fixedFeeAmount; - } - - async function mirrorNodeFeeEqualsCustomFixedFee(customFixedFee, feeCollectorAccountId, amount) { - return feeCollectorAccountId === customFixedFee.collector_account_id && - amount === customFixedFee.amount; - } - - async function mirrorNodeFeeEqualsCustomFractionalFee(customFractionalFee, feeCollectorAccountId, numerator, denominator, minAmount, maxAmount, assessmentMethod) { - return feeCollectorAccountId === customFractionalFee.collector_account_id && - numerator === customFractionalFee.amount.numerator && - denominator === customFractionalFee.amount.denominator && - minAmount === customFractionalFee.minimum && - maxAmount === customFractionalFee.maximum && - ((assessmentMethod === "exclusive") === customFractionalFee.net_of_transfer); - } - - async function mirrorNodeFeeEqualsCustomRoyaltyFee(customRoyaltyFee, feeCollectorAccountId, numerator, denominator, fixedFeeAmount) { - return feeCollectorAccountId === customRoyaltyFee.collector_account_id && - numerator === customRoyaltyFee.amount.numerator && - denominator === customRoyaltyFee.amount.denominator && - fixedFeeAmount === customRoyaltyFee.fallback_fee.amount; - } - - async function verifyTokenCreationWithFixedFee(tokenId, feeCollectorAccountId, feeCollectorsExempt, amount) { - const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); - const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId).tokens[0]; - - let foundConsensusNodeFee = false; - let foundMirrorNodeFee = false; - - for (let i = 0; i < consensusNodeInfo.customFees.size(); i++) { - if (consensusNodeInfo.customFees[i] instanceof CustomFixedFee && - consensusNodeFeeEqualsCustomFixedFee(consensusNodeInfo.customFees[i], feeCollectorAccountId, feeCollectorsExempt, amount)) { - foundConsensusNodeFee = true; - break; - } - } - - for (let i = 0; i < mirrorNodeInfo.custom_fees.fixed_fees.size(); i++) { - if (mirrorNodeFeeEqualsCustomFixedFee(mirrorNodeInfo.custom_fees.fixed_fees[i], feeCollectorAccountId, amount)) { - foundMirrorNodeFee = true; - break; - } - } - - expect(foundConsensusNodeFee).to.be.true; - expect(foundMirrorNodeFee).to.be.true; - } - - async function verifyTokenCreationWithFractionalFee(tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod) { - const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); - const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId).tokens[0]; - - let foundConsensusNodeFee = false; - let foundMirrorNodeFee = false; - - for (let i = 0; i < consensusNodeInfo.customFees.size(); i++) { - if (consensusNodeInfo.customFees[i] instanceof CustomFractionalFee && - consensusNodeFeeEqualsCustomFractionalFee(consensusNodeInfo.customFees[i], feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minAmount, maxAmount, assessmentMethod)) { - foundConsensusNodeFee = true; - break; - } - } - - for (let i = 0; i < mirrorNodeInfo.custom_fees.fractional_fees.size(); i++) { - if (mirrorNodeFeeEqualsCustomFractionalFee(mirrorNodeInfo.custom_fees.fractional_fees[i], feeCollectorAccountId, numerator, denominator, minAmount, maxAmount, assessmentMethod)) { - foundMirrorNodeFee = true; - break; - } - } - - expect(foundConsensusNodeFee).to.be.true; - expect(foundMirrorNodeFee).to.be.true; - } - - async function verifyTokenCreationWithRoyaltyFee(tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeAmount) { - const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); - const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId).tokens[0]; - - let foundConsensusNodeFee = false; - let foundMirrorNodeFee = false; - - for (let i = 0; i < consensusNodeInfo.customFees.size(); i++) { - if (consensusNodeInfo.customFees[i] instanceof CustomRoyaltyFee && - consensusNodeFeeEqualsCustomRoyaltyFee(consensusNodeInfo.customFees[i], feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, fixedFeeAmount)) { - foundConsensusNodeFee = true; - break; - } - } - - for (let i = 0; i < mirrorNodeInfo.custom_fees.fractional_fees.size(); i++) { - if (mirrorNodeFeeEqualsCustomRoyaltyFee(mirrorNodeInfo.custom_fees.fractional_fees[i], feeCollectorAccountId, numerator, denominator, fixedFeeAmount)) { - foundMirrorNodeFee = true; - break; - } - } - - expect(foundConsensusNodeFee).to.be.true; - expect(foundMirrorNodeFee).to.be.true; - } - - it("(#1) Creates a token with a fixed fee with an amount of 0", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 0 - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#2) Creates a token with a fixed fee with an amount of -1", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: -1 - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#3) Creates a token with a fixed fee with an amount of 9,223,372,036,854,775,807 (int64 max)", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const amount = 9223372036854775807n; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fixedFee: { - amount: amount - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); - }); - - it("(#4) Creates a token with a fixed fee with an amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const amount = 9223372036854775806n; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fixedFee: { - amount: amount - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, amount); - }); - - it("(#5) Creates a token with a fixed fee with an amount of 9,223,372,036,854,775,8068 (int64 max + 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 9223372036854775808n - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#6) Creates a token with a fixed fee with an amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 18446744073709551615n - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#7) Creates a token with a fixed fee with an amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 18446744073709551614n - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#8) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,808 (int64 min)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: -9223372036854775808n - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#9) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: -9223372036854775807n - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#10) Creates a token with a fractional fee with a numerator of 0", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 0, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#11) Creates a token with a fractional fee with a numerator of -1", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: -1, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#12) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,807 (int64 max)", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 9223372036854775807n; - const denominator = 10; - const minimumAmount = 1; - const maximumAmount = 10; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minimumAmount, - maximumAmount: maximumAmount, - assessmentMethod: assessmentMethod - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); - }); - - it("(#13) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 9223372036854775806n; - const denominator = 10; - const minimumAmount = 1; - const maximumAmount = 10; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minimumAmount, - maximumAmount: maximumAmount, - assessmentMethod: assessmentMethod - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); - }); - - it("(#14) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 9223372036854775808n, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#15) Creates a token with a fractional fee with a numerator of 18,446,744,073,709,551,615 (uint64 max)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 18446744073709551615n, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#16) Creates a token with a fractional fee with a numerator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 18446744073709551614n, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#17) Creates a token with a fractional fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: -9223372036854775808n, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#18) Creates a token with a fractional fee with a numerator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: -9223372036854775807n, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#19) Creates a token with a fractional fee with a denominator of 0", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 0, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "FRACTION_DIVIDES_BY_ZERO"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#20) Creates a token with a fractional fee with a denominator of -1", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: -1, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#21) Creates a token with a fractional fee with a denominator of 9,223,372,036,854,775,807 (int64 max)", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 9223372036854775807n; - const minimumAmount = 1; - const maximumAmount = 10; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minimumAmount, - maximumAmount: maximumAmount, - assessmentMethod: assessmentMethod - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); - }); - - it("(#22) Creates a token with a fractional fee with a denominator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 9223372036854775806n; - const minimumAmount = 1; - const maximumAmount = 10; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minimumAmount, - maximumAmount: maximumAmount, - assessmentMethod: assessmentMethod - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); - }); - - it("(#23) Creates a token with a fractional fee with a denominator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 9223372036854775808n, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#24) Creates a token with a fractional fee with a denominator of 18,446,744,073,709,551,615 (uint64 max)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 18446744073709551615n, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#25) Creates a token with a fractional fee with a denominator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 18446744073709551614n, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#26) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: -9223372036854775808n, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#27) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: -9223372036854775807n, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#28) Creates a token with a fractional fee with a minimum amount of 0", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const minimumAmount = 0; - const maximumAmount = 10; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minimumAmount, - maximumAmount: maximumAmount, - assessmentMethod: assessmentMethod - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); - }); - - it("(#29) Creates a token with a fractional fee with a minimum amount of -1", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: -1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#30) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,807 (int64 max)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 9223372036854775807n, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#31) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 9223372036854775806n, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#32) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 9223372036854775808n, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#33) Creates a token with a fractional fee with a minimum amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 18446744073709551615n, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#34) Creates a token with a fractional fee with a minimum amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 18446744073709551614n, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#35) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: -9223372036854775808n, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#36) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: -9223372036854775807n, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#37) Creates a token with a fractional fee with a maximum amount of 0", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const minimumAmount = 1; - const maximumAmount = 0; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minimumAmount, - maximumAmount: maximumAmount, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); - }); - - it("(#38) Creates a token with a fractional fee with a maximum amount of -1", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 1, - maximumAmount: -1, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#39) Creates a token with a fractional fee with a maximum amount of 9,223,372,036,854,775,807 (int64 max)", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const minimumAmount = 1; - const maximumAmount = 9223372036854775807n; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minimumAmount, - maximumAmount: maximumAmount, - assessmentMethod: assessmentMethod - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); - }); - - it("(#40) Creates a token with a fractional fee with a maximum amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const minimumAmount = 1; - const maximumAmount = 9223372036854775806n; - const assessmentMethod = "inclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minimumAmount, - maximumAmount: maximumAmount, - assessmentMethod: assessmentMethod - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); - }); - - it("(#41) Creates a token with a fractional fee with a maximum amount of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 1, - maximumAmount: 9223372036854775808n, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#42) Creates a token with a fractional fee with a maximum amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 1, - maximumAmount: 18446744073709551615n, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#43) Creates a token with a fractional fee with a maximum amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 1, - maximumAmount: 18446744073709551614n, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#44) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 1, - maximumAmount: -9223372036854775808n, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#45) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 1, - maximumAmount: -9223372036854775807n, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#46) Creates a token with a royalty fee with a numerator of 0", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 0, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#47) Creates a token with a royalty fee with a numerator of -1", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: -1, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#48) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,807 (int64 max)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 9223372036854775807n, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "ROYALTY_FRACTION_CANNOT_EXCEED_ONE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#49) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 9223372036854775806n, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "ROYALTY_FRACTION_CANNOT_EXCEED_ONE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#50) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 9223372036854775808n, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#51) Creates a token with a royalty fee with a numerator of 18,446,744,073,709,551,615 (uint64 max)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 18446744073709551615n, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#52) Creates a token with a royalty fee with a numerator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 18446744073709551614n, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#53) Creates a token with a royalty fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: -9223372036854775808n, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#54) Creates a token with a royalty fee with a numerator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: -9223372036854775807n, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#55) Creates a token with a royalty fee with a denominator of 0", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 0, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "FRACTION_DIVIDES_BY_ZERO"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#56) Creates a token with a royalty fee with a denominator of -1", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: -1, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#57) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,807 (int64 max)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 9223372036854775807n; - const fallbackFeeAmount = 10; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - royaltyFee: { - numerator: numerator, - denominator: denominator, - fallbackFee: { - amount: fallbackFeeAmount - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); - }); - - it("(#58) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 9223372036854775806n; - const fallbackFeeAmount = 10; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - royaltyFee: { - numerator: numerator, - denominator: denominator, - fallbackFee: { - amount: fallbackFeeAmount - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); - }); - - it("(#59) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 9223372036854775808n, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#60) Creates a token with a royalty fee with a denominator of 18,446,744,073,709,551,615 (uint64 max)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 18446744073709551615n, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#61) Creates a token with a royalty fee with a denominator of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 18446744073709551614n, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#62) Creates a token with a royalty fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: -9223372036854775808n, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#63) Creates a token with a royalty fee with a denominator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: -9223372036854775807n, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#64) Creates a token with a royalty fee with a fallback fee with an amount of 0", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - amount: 0 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#65) Creates a token with a royalty fee with a fallback fee with an amount of -1", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - amount: -1 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#66) Creates a token with a royalty fee with a fallback fee with an amount of 9,223,372,036,854,775,807 (int64 max)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const fallbackFeeAmount = 9223372036854775807n; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - royaltyFee: { - numerator: numerator, - denominator: denominator, - fallbackFee: { - amount: fallbackFeeAmount - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); - }); - - it("(#67) Creates a token with a royalty fee with a fallback fee with an amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const fallbackFeeAmount = 9223372036854775806n; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - royaltyFee: { - numerator: numerator, - denominator: denominator, - fallbackFee: { - amount: fallbackFeeAmount - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithRoyaltyFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, feeCollectorAccountId, feeCollectorsExempt, fallbackFeeAmount); - }); - - it("(#68) Creates a token with a royalty fee with a fallback fee with an amount of 9,223,372,036,854,775,808 (int64 max + 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - amount: 9223372036854775808n - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#69) Creates a token with a royalty fee with a fallback fee with an amount of 18,446,744,073,709,551,615 (uint64 max)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - amount: 18446744073709551615n - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#70) Creates a token with a royalty fee with a fallback fee with an amount of 18,446,744,073,709,551,614 (uint64 max - 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - amount: 18446744073709551614n - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#71) Creates a token with a royalty fee with a fallback fee with an amount of -9,223,372,036,854,775,808 (int64 min)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - amount: -9223372036854775808n - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#72) Creates a token with a royalty fee with a fallback fee with an amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - amount: -9223372036854775807n - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#73) Creates a token with a fixed fee with a fee collector account that doesn't exist", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: "123.456.789", - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#74) Creates a token with a fractional with a fee collector account that doesn't exist", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: "123.456.789", - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#75) Creates a token with a royalty fee with a fee collector account that doesn't exist", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: "123.456.789", - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#76) Creates a token with a fixed fee with an empty fee collector account", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: "", - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.code, -32603); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#77) Creates a token with a fractional with an empty fee collector account", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: "", - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.code, -32603); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#78) Creates a token with a royalty fee with an empty fee collector account", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: "", - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.code, -32603); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#79) Creates a token with a fixed fee with a deleted fee collector account", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - response = await JSONRPCRequest("createAccount", { - key: key - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const accountId = response.accountId; - - response = await JSONRPCRequest("deleteAccount", { - deleteAccountId: accountId, - transferAccountId: process.env.OPERATOR_ACCOUNT_ID, - commonTransactionParams: { - signers: [ - key - ] - } - }) - if (response.status === "NOT_IMPLEMENTED") this.skip(); + it("(#10) Updates a mutable token with an invalid key as its fee schedule key", async function () { try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: accountId, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - } - ], + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { signers: [ - key + mutableTokenAdminKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + assert.equal(err.code, -32603, "Internal error"); return; } assert.fail("Should throw an error"); }); + }); + + describe("Pause Key", function () { + async function verifyTokenPauseKeyUpdate(tokenId, pauseKey) { + expect(pauseKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).pauseKey.toStringDer()); + expect(pauseKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].pause_key); + } - it("(#80) Creates a token with a fractional fee with a deleted fee collector account", async function () { + it("(#1) Updates an immutable token with a valid key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - response = await JSONRPCRequest("createAccount", { - key: key - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const accountId = response.accountId; - - response = await JSONRPCRequest("deleteAccount", { - deleteAccountId: accountId, - transferAccountId: process.env.OPERATOR_ACCOUNT_ID, - commonTransactionParams: { - signers: [ - key - ] - } - }) - if (response.status === "NOT_IMPLEMENTED") this.skip(); - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: accountId, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ], - commonTransactionParams: { - signers: [ - key - ] - } + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + feeScheduleKey: key }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } - + assert.fail("Should throw an error"); }); - it("(#81) Creates a token with a royalty fee with a deleted fee collector account", async function () { + it("(#2) Updates a mutable token with a valid ED25519 public key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; + const privateKey = response.key; - response = await JSONRPCRequest("createAccount", { - key: key + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const accountId = response.accountId; + const publicKey = response.key; - response = await JSONRPCRequest("deleteAccount", { - deleteAccountId: accountId, - transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: publicKey, commonTransactionParams: { signers: [ - key + mutableTokenAdminKey, + privateKey ] } - }) - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: accountId, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - amount: 10 - } - } - } - ], - commonTransactionParams: { - signers: [ - key - ] - } - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#82) Creates a token with a fixed fee that is assessed with the created token", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const fixedFeeAmount = 10; - const denominatingTokenId = "0.0.0"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fixedFee: { - amount: fixedFeeAmount, - denominatingTokenId: denominatingTokenId - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenCreationWithFixedFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, fixedFeeAmount); - }); - - it("(#83) Creates a token with a fixed fee that is assessed with a token that doesn't exist", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10, - denominatingTokenId: "123.456.789" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#84) Creates a token with a fixed fee that is assessed with an empty token", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10, - denominatingTokenId: "" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.code, -32603); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#85) Creates a token with a fixed fee that is assessed with a deleted token", async function () { - let response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const tokenId = response.tokenId; - - response = await JSONRPCRequest("deleteToken", { - tokenId: tokenId - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10, - denominatingTokenId: tokenId - } - } - ] - }); - } catch (err) { - assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#86) Creates a token with a fractional fee that is assessed to the receiver", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; - const feeCollectorsExempt = false; - const numerator = 1; - const denominator = 10; - const minimumAmount = 1; - const maximumAmount = 10; - const assessmentMethod = "exclusive"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: feeCollectorAccountId, - feeCollectorsExempt: feeCollectorsExempt, - fractionalFee: { - numerator: numerator, - denominator: denominator, - minimumAmount: minimumAmount, - maximumAmount: maximumAmount, - assessmentMethod: assessmentMethod - } - } - ] }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithFractionalFee(response.tokenId, feeCollectorAccountId, feeCollectorsExempt, numerator, denominator, minimumAmount, maximumAmount, assessmentMethod); - }); - - it("(#87) Creates a fungible token with a royalty fee", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - royaltyFee: { - numerator: 1, - denominator: 10, - fallbackFee: { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - amount: 10 - } - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_ROYALTY_FEE_ONLY_ALLOWED_FOR_NON_FUNGIBLE_UNIQUE"); - return; - } - - assert.fail("Should throw an error"); + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + verifyTokenPauseKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#88) Creates an NFT with a fractional fee", async function () { + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const key = response.key; - - try { - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - supplyKey: key, - tokenType: "nft", - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fractionalFee: { - numerator: 1, - denominator: 10, - minimumAmount: 1, - maximumAmount: 10, - assessmentMethod: "inclusive" - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FRACTIONAL_FEE_ONLY_ALLOWED_FOR_FUNGIBLE_COMMON"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#89) Creates a token with more than the maximum amount of fees allowed", async function () { - try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - customFees: [ - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - }, - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - }, - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - }, - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - }, - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - }, - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - }, - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - }, - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - }, - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - }, - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - }, - { - feeCollectorAccountId: process.env.OPERATOR_ACCOUNT_ID, - feeCollectorsExempt: false, - fixedFee: { - amount: 10 - } - } - ] - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "CUSTOM_FEES_LIST_TOO_LONG"); - return; - } - - assert.fail("Should throw an error"); - }); - }); - - describe("Pause Key", function () { - async function verifyTokenCreationWithPauseKey(tokenId, pauseKey) { - expect(pauseKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).pauseKey.toStringDer()); - expect(pauseKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].pause_key); - } - - it("(#1) Creates a token with a valid ED25519 public key as its pause key", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" - }); - const publicKey = response.key; - - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: publicKey - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); - }); + const privateKey = response.key; - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its pause key", async function () { - let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: publicKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenPauseKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#3) Creates a token with a valid ED25519 private key as its pause key", async function () { + it("(#4) Updates a mutable token with a valid ED25519 private key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -5907,19 +3386,23 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: privateKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenPauseKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its pause key", async function () { + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); @@ -5932,20 +3415,23 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithPauseKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenPauseKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { + const keyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -5962,22 +3448,28 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const keyList = response.key; + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: keyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithPauseKey(response.tokenId, keyList); + verifyTokenPauseKeyUpdate(response.tokenId, keyList.key); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its pause key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its pause key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -6015,22 +3507,30 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const nestedKeyList = response.key; + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: nestedKeyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithPauseKey(response.tokenId, nestedKeyList); + verifyTokenPauseKeyUpdate(response.tokenId, nestedKeyList.key); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -6045,27 +3545,59 @@ describe("TokenCreateTransaction", function () { } ] }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const thresholdKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: thresholdKey + verifyTokenPauseKeyUpdate(response.tokenId, thresholdKey.key); + }); + + it("(#9) Updates a mutable token with a valid key as its pause key but doesn't sign with it", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } - verifyTokenCreationWithPauseKey(response.tokenId, thresholdKey); + assert.fail("Should throw an error"); }); - it("(#8) Creates a token with an invalid key as its pause key", async function () { + it("(#10) Updates a mutable token with an invalid key as its pause key", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - pauseKey: crypto.randomBytes(88).toString("hex") + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -6078,81 +3610,145 @@ describe("TokenCreateTransaction", function () { }); describe("Metadata", function () { - async function verifyTokenCreationWithMetadata(tokenId, metadata) { + async function verifyTokenMetadataUpdate(tokenId, metadata) { expect(metadata).to.equal(await consensusInfoClient.getTokenInfo(tokenId).metadata); expect(metadata).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].metadata); } + + it("(#1) Updates an immutable token with metadata", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + metadata: "1234" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } - it("(#1) Creates a token with metadata", async function () { + assert.fail("Should throw an error"); + }); + + it("(#2) Updates a mutable token with metadata", async function () { const metadata = "1234"; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadata: metadata + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadata: metadata, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithMetadata(response.tokenId, metadata); + verifyTokenMetadataUpdate(response.tokenId, metadata); }); - it("(#2) Creates a token with empty metadata", async function () { + it("(#3) Updates a mutable token with empty metadata", async function () { const metadata = ""; - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadata: metadata + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadata: metadata, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithMetadata(response.tokenId, metadata); + verifyTokenMetadataUpdate(response.tokenId, metadata); }); }); describe("Metadata Key", function () { - async function verifyTokenCreationWithMetadataKey(tokenId, metadataKey) { + async function verifyTokenMetadataKeyUpdate(tokenId, metadataKey) { expect(metadataKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).metadataKey.toStringDer()); expect(metadataKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].metadata_key); } - it("(#1) Creates a token with a valid ED25519 public key as its metadata key", async function () { + it("(#1) Updates an immutable token with a valid key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey" }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + metadataKey: key + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Updates a mutable token with a valid ED25519 public key as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ed25519PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey + }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: publicKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadataKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenMetadataKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its metadata key", async function () { + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PrivateKey" + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const privateKey = response.key; + + response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: publicKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadataKey: publicKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenMetadataKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#3) Creates a token with a valid ED25519 private key as its metadata key", async function () { + it("(#4) Updates a mutable token with a valid ED25519 private key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PrivateKey" }); @@ -6165,19 +3761,23 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadataKey: privateKey, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenMetadataKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its metadata key", async function () { + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PrivateKey" }); @@ -6190,20 +3790,23 @@ describe("TokenCreateTransaction", function () { }); const publicKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: privateKey + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadataKey: privateKey, + commonTransactionParams: { + signers: [ + privateKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenCreationWithMetadataKey(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenMetadataKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { + const keyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -6220,22 +3823,28 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const keyList = response.key; + if (keyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: keyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadataKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithMetadataKey(response.tokenId, keyList.key); + verifyTokenMetadataKeyUpdate(response.tokenId, keyList.key); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its metadata key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its metadata key", async function () { + const nestedKeyList = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -6273,22 +3882,30 @@ describe("TokenCreateTransaction", function () { } ] }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const nestedKeyList = response.key; + if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: nestedKeyList + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadataKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5] + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenCreationWithMetadataKey(response.tokenId, nestedKeyList.key); + verifyTokenMetadataKeyUpdate(response.tokenId, nestedKeyList.key); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { - let response = await JSONRPCRequest("generateKey", { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { + const thresholdKey = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -6303,27 +3920,59 @@ describe("TokenCreateTransaction", function () { } ] }); + if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadataKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1] + ] + } + }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const thresholdKey = response.key; - response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: thresholdKey + verifyTokenMetadataKeyUpdate(response.tokenId, thresholdKey.key); + }); + + it("(#9) Updates a mutable token with a valid key as its metadata key but doesn't sign with it", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + try { + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadataKey: key, + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } - verifyTokenCreationWithMetadataKey(response.tokenId, thresholdKey.key); + assert.fail("Should throw an error"); }); - it("(#8) Creates a token with an invalid key as its metadata key", async function () { + it("(#10) Updates a mutable token with an invalid key as its metadata key", async function () { try { - const response = await JSONRPCRequest("createToken", { - name: "testname", - symbol: "testsymbol", - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - metadataKey: crypto.randomBytes(88).toString("hex") + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadataKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [ + mutableTokenAdminKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { From 170985e0d13948bee79b3fb5139d32d49786bfdc Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Wed, 11 Sep 2024 14:40:34 -0400 Subject: [PATCH 19/25] feat: add remaining tests Signed-off-by: Rob Walworth --- consensusInfoClient.js | 2 +- .../test_tokenUpdateTransaction.js | 753 +++++++++--------- 2 files changed, 397 insertions(+), 358 deletions(-) diff --git a/consensusInfoClient.js b/consensusInfoClient.js index 1a0674a..ea74232 100644 --- a/consensusInfoClient.js +++ b/consensusInfoClient.js @@ -3,7 +3,7 @@ import { AccountBalanceQuery, AccountId, AccountInfoQuery, Client, TokenInfoQuer class ConsensusInfoClient { constructor() { if (process.env.NODE_IP && process.env.NODE_ACCOUNT_ID && process.env.MIRROR_NETWORK) { - const node = { [process.env.NODE_IP]: new AccountId(parseInt(process.env.NODE_ACCOUNT_ID)) }; + const node = { [process.env.NODE_IP]: AccountId.fromString(process.env.NODE_ACCOUNT_ID) }; this.sdkClient = Client.forNetwork(node); } else { this.sdkClient = Client.forTestnet(); diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js index df1781f..0db40ca 100644 --- a/test/token-service/test_tokenUpdateTransaction.js +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -4,6 +4,7 @@ import consensusInfoClient from "../../consensusInfoClient.js"; import { setOperator } from "../../setup_Tests.js"; import crypto from "crypto"; import { assert, expect } from "chai"; +import { JSONRPC } from "json-rpc-2.0"; // Needed to convert BigInts to JSON number format. BigInt.prototype.toJSON = function () { @@ -13,7 +14,7 @@ BigInt.prototype.toJSON = function () { /** * Tests for TokenUpdateTransaction */ -describe("TokenCreateTransaction", function () { +describe("TokenUpdateTransaction", function () { // Tests should not take longer than 30 seconds to fully execute. this.timeout(30000); @@ -24,13 +25,13 @@ describe("TokenCreateTransaction", function () { const initialSupply = 1000000; // Two tokens should be created. One immutable token (no admin key) and another mutable. - let immutableTokenId, mutableTokenId, mutableTokenAdminKey; + let immutableTokenId, mutableTokenId, mutableTokenKey; - // Some tests require an immutable token. Since it's immutable only one needs to be created. before(async function () { - setOperator(process.env.OPERATOR_ACCOUNT_ID, process.env.OPERATOR_ACCOUNT_PRIVATE_KEY); + await setOperator(process.env.OPERATOR_ACCOUNT_ID, process.env.OPERATOR_ACCOUNT_PRIVATE_KEY); - let response = JSONRPCRequest("createToken", { + // Generate an immutable key. + const response = await JSONRPCRequest("createToken", { name: initialTokenName, symbol: initialTokenSymbol, treasuryAccountId: initialTreasuryAccountId, @@ -39,6 +40,8 @@ describe("TokenCreateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); immutableTokenId = response.tokenId; + + await JSONRPCRequest("reset"); }); beforeEach(async function () { @@ -48,15 +51,27 @@ describe("TokenCreateTransaction", function () { type: "ecdsaSecp256k1PrivateKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - mutableTokenAdminKey = response.key; + mutableTokenKey = response.key; response = await JSONRPCRequest("createToken", { name: initialTokenName, symbol: initialTokenSymbol, treasuryAccountId: initialTreasuryAccountId, - adminKey: mutableTokenAdminKey, + adminKey: mutableTokenKey, + kycKey: mutableTokenKey, + freezeKey: mutableTokenKey, + wipeKey: mutableTokenKey, + supplyKey: mutableTokenKey, initialSupply: initialSupply, - tokenType: "ft" + tokenType: "ft", + feeScheduleKey: mutableTokenKey, + pauseKey: mutableTokenKey, + metadataKey: mutableTokenKey, + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); mutableTokenId = response.tokenId; @@ -93,9 +108,7 @@ describe("TokenCreateTransaction", function () { it("(#3) Updates a token with no token ID", async function () { try { - const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId - }); + const response = await JSONRPCRequest("updateToken", {}); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_TOKEN_ID"); @@ -114,7 +127,7 @@ describe("TokenCreateTransaction", function () { it("(#1) Updates an immutable token with a symbol", async function () { try { - const response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, symbol: "t" }); @@ -134,7 +147,7 @@ describe("TokenCreateTransaction", function () { symbol: symbol, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -149,7 +162,7 @@ describe("TokenCreateTransaction", function () { symbol: "", commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -166,7 +179,7 @@ describe("TokenCreateTransaction", function () { symbol: symbol, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -182,7 +195,7 @@ describe("TokenCreateTransaction", function () { symbol: "This is a long symbol that is not valid because it exceeds 100 characters and it should fail the test", commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -219,7 +232,7 @@ describe("TokenCreateTransaction", function () { it("(#1) Updates an immutable token with a name", async function () { try { - const response = await JSONRPCRequest("createToken", { + const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, name: "t" }); @@ -239,7 +252,7 @@ describe("TokenCreateTransaction", function () { name: name, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -254,7 +267,7 @@ describe("TokenCreateTransaction", function () { name: "", commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -271,7 +284,7 @@ describe("TokenCreateTransaction", function () { name: name, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -287,7 +300,7 @@ describe("TokenCreateTransaction", function () { name: "This is a long name that is not valid because it exceeds 100 characters and it should fail the test!!", commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -339,8 +352,10 @@ describe("TokenCreateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; + // Create with 1 auto token association in order to automatically associate with the created token. response = await JSONRPCRequest("createAccount", { key: key, + maxAutoTokenAssociations: 1 }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const accountId = response.accountId; @@ -350,25 +365,25 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: accountId, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, key ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - expect(accountId).to.equal(await consensusInfoClient.getTokenInfo(tokenId).treasuryAccountId.toString()); - expect(accountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].treasury_account_id); + const tokenInfo = await consensusInfoClient.getTokenInfo(mutableTokenId); + expect(accountId).to.equal(tokenInfo.treasuryAccountId.toString()); // Make sure the tokens were transferred from the initial treasury account to the new treasury account. const initialTreasuryAccountBalance = await consensusInfoClient.getBalance(process.env.OPERATOR_ACCOUNT_ID); const newTreasuryAccountBalance = await consensusInfoClient.getBalance(accountId); - assert(initialTreasuryAccountBalance.tokens.has(mutableTokenId)).is.true; - assert(newTreasuryAccountBalance.tokens.has(mutableTokenId)).is.true; + assert(initialTreasuryAccountBalance.tokens._map.has(mutableTokenId)); + assert(newTreasuryAccountBalance.tokens._map.has(mutableTokenId)); - expect(initialTreasuryAccountBalance.tokens.get(mutableTokenId).size).to.equal(0); - expect(newTreasuryAccountBalance.tokens.get(mutableTokenId).size).to.equal(initialSupply); + expect(initialTreasuryAccountBalance.tokens._map.get(mutableTokenId).toString()).to.equal("0"); + expect(newTreasuryAccountBalance.tokens._map.get(mutableTokenId).toString()).to.equal(initialSupply.toString()); }); it("(#3) Updates a mutable token with a treasury account without signing with the account's private key", async function () { @@ -386,11 +401,11 @@ describe("TokenCreateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenAdminKey, + tokenId: mutableTokenId, treasuryAccountId: accountId, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -410,7 +425,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: "123.456.789", commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -449,11 +464,11 @@ describe("TokenCreateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenAdminKey, + tokenId: mutableTokenId, treasuryAccountId: accountId, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, key ] } @@ -482,7 +497,7 @@ describe("TokenCreateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenAdminKey, + tokenId: mutableTokenId, treasuryAccountId: accountId, commonTransactionParams: { signers: [ @@ -545,7 +560,7 @@ describe("TokenCreateTransaction", function () { adminKey: publicKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, privateKey ] } @@ -574,7 +589,7 @@ describe("TokenCreateTransaction", function () { adminKey: publicKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, privateKey ] } @@ -603,7 +618,7 @@ describe("TokenCreateTransaction", function () { adminKey: privateKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, privateKey ] } @@ -632,6 +647,7 @@ describe("TokenCreateTransaction", function () { adminKey: privateKey, commonTransactionParams: { signers: [ + mutableTokenKey, privateKey ] } @@ -667,7 +683,7 @@ describe("TokenCreateTransaction", function () { adminKey: keyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, keyList.privateKeys[0], keyList.privateKeys[1], keyList.privateKeys[2], @@ -726,7 +742,7 @@ describe("TokenCreateTransaction", function () { adminKey: nestedKeyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, nestedKeyList.privateKeys[0], nestedKeyList.privateKeys[1], nestedKeyList.privateKeys[2], @@ -764,6 +780,7 @@ describe("TokenCreateTransaction", function () { adminKey: thresholdKey.key, commonTransactionParams: { signers: [ + mutableTokenKey, thresholdKey.privateKeys[0], thresholdKey.privateKeys[1] ] @@ -787,7 +804,7 @@ describe("TokenCreateTransaction", function () { adminKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -807,7 +824,7 @@ describe("TokenCreateTransaction", function () { adminKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -850,60 +867,46 @@ describe("TokenCreateTransaction", function () { it("(#2) Updates a mutable token with a valid ED25519 public key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey", - fromKey: privateKey - }); - const publicKey = response.key; + const key = response.key; response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - kycKey: publicKey, + kycKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenKycKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenKycKeyUpdate(response.tokenId, String(key).substring(24).toLowerCase()); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey - }); - const publicKey = response.key; + const key = response.key; response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - kycKey: publicKey, + kycKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenKycKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenKycKeyUpdate(response.tokenId, String(key).substring(28).toLowerCase()); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its KYC key", async function () { @@ -924,7 +927,7 @@ describe("TokenCreateTransaction", function () { kycKey: privateKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, privateKey ] } @@ -953,7 +956,7 @@ describe("TokenCreateTransaction", function () { kycKey: privateKey, commonTransactionParams: { signers: [ - privateKey + mutableTokenKey ] } }); @@ -988,7 +991,7 @@ describe("TokenCreateTransaction", function () { kycKey: keyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, keyList.privateKeys[0], keyList.privateKeys[1], keyList.privateKeys[2], @@ -1047,7 +1050,7 @@ describe("TokenCreateTransaction", function () { kycKey: nestedKeyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, nestedKeyList.privateKeys[0], nestedKeyList.privateKeys[1], nestedKeyList.privateKeys[2], @@ -1085,6 +1088,7 @@ describe("TokenCreateTransaction", function () { kycKey: thresholdKey.key, commonTransactionParams: { signers: [ + mutableTokenKey, thresholdKey.privateKeys[0], thresholdKey.privateKeys[1] ] @@ -1095,30 +1099,46 @@ describe("TokenCreateTransaction", function () { verifyTokenKycKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#9) Updates a mutable token with a valid key as its KYC key but doesn't sign with it", async function () { + it("(#9) Updates a mutable token that doesn't have a KYC key with a valid key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; + response = await JSONRPCRequest("createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + const tokenId = response.tokenId; + try { response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, + tokenId: tokenId, kycKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); + assert.equal(err.data.status, "TOKEN_HAS_NO_KYC_KEY"); return; } assert.fail("Should throw an error"); + }); it("(#10) Updates a mutable token with an invalid key as its KYC key", async function () { @@ -1128,7 +1148,7 @@ describe("TokenCreateTransaction", function () { kycKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -1187,8 +1207,7 @@ describe("TokenCreateTransaction", function () { freezeKey: publicKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -1216,8 +1235,7 @@ describe("TokenCreateTransaction", function () { freezeKey: publicKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -1245,8 +1263,7 @@ describe("TokenCreateTransaction", function () { freezeKey: privateKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -1274,7 +1291,7 @@ describe("TokenCreateTransaction", function () { freezeKey: privateKey, commonTransactionParams: { signers: [ - privateKey + mutableTokenKey ] } }); @@ -1309,7 +1326,7 @@ describe("TokenCreateTransaction", function () { freezeKey: keyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, keyList.privateKeys[0], keyList.privateKeys[1], keyList.privateKeys[2], @@ -1368,7 +1385,7 @@ describe("TokenCreateTransaction", function () { freezeKey: nestedKeyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, nestedKeyList.privateKeys[0], nestedKeyList.privateKeys[1], nestedKeyList.privateKeys[2], @@ -1406,6 +1423,7 @@ describe("TokenCreateTransaction", function () { freezeKey: thresholdKey.key, commonTransactionParams: { signers: [ + mutableTokenKey, thresholdKey.privateKeys[0], thresholdKey.privateKeys[1] ] @@ -1416,26 +1434,41 @@ describe("TokenCreateTransaction", function () { verifyTokenFreezeKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#9) Updates a mutable token with a valid key as its freeze key but doesn't sign with it", async function () { + it("(#9) Updates a mutable token that doesn't have a freeze key with a valid key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; + response = await JSONRPCRequest("createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + const tokenId = response.tokenId; + try { response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, + tokenId: tokenId, freezeKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); + assert.equal(err.data.status, "TOKEN_HAS_NO_FREEZE_KEY"); return; } @@ -1449,7 +1482,7 @@ describe("TokenCreateTransaction", function () { freezeKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -1508,8 +1541,7 @@ describe("TokenCreateTransaction", function () { wipeKey: publicKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -1537,8 +1569,7 @@ describe("TokenCreateTransaction", function () { wipeKey: publicKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -1566,8 +1597,7 @@ describe("TokenCreateTransaction", function () { wipeKey: privateKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -1595,7 +1625,7 @@ describe("TokenCreateTransaction", function () { wipeKey: privateKey, commonTransactionParams: { signers: [ - privateKey + mutableTokenKey ] } }); @@ -1630,7 +1660,7 @@ describe("TokenCreateTransaction", function () { wipeKey: keyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, keyList.privateKeys[0], keyList.privateKeys[1], keyList.privateKeys[2], @@ -1689,7 +1719,7 @@ describe("TokenCreateTransaction", function () { wipeKey: nestedKeyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, nestedKeyList.privateKeys[0], nestedKeyList.privateKeys[1], nestedKeyList.privateKeys[2], @@ -1727,6 +1757,7 @@ describe("TokenCreateTransaction", function () { wipeKey: thresholdKey.key, commonTransactionParams: { signers: [ + mutableTokenKey, thresholdKey.privateKeys[0], thresholdKey.privateKeys[1] ] @@ -1737,26 +1768,41 @@ describe("TokenCreateTransaction", function () { verifyTokenWipeKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#9) Updates a mutable token with a valid key as its wipe key but doesn't sign with it", async function () { + it("(#9) Updates a mutable token that doesn't have a wipe key with a valid key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; + response = await JSONRPCRequest("createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + const tokenId = response.tokenId; + try { response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, + tokenId: tokenId, wipeKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); + assert.equal(err.data.status, "TOKEN_HAS_NO_WIPE_KEY"); return; } @@ -1770,7 +1816,7 @@ describe("TokenCreateTransaction", function () { wipeKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -1829,8 +1875,7 @@ describe("TokenCreateTransaction", function () { supplyKey: publicKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -1858,8 +1903,7 @@ describe("TokenCreateTransaction", function () { supplyKey: publicKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -1887,8 +1931,7 @@ describe("TokenCreateTransaction", function () { supplyKey: privateKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -1916,7 +1959,7 @@ describe("TokenCreateTransaction", function () { supplyKey: privateKey, commonTransactionParams: { signers: [ - privateKey + mutableTokenKey ] } }); @@ -1951,7 +1994,7 @@ describe("TokenCreateTransaction", function () { supplyKey: keyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, keyList.privateKeys[0], keyList.privateKeys[1], keyList.privateKeys[2], @@ -2010,7 +2053,7 @@ describe("TokenCreateTransaction", function () { supplyKey: nestedKeyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, nestedKeyList.privateKeys[0], nestedKeyList.privateKeys[1], nestedKeyList.privateKeys[2], @@ -2048,6 +2091,7 @@ describe("TokenCreateTransaction", function () { supplyKey: thresholdKey.key, commonTransactionParams: { signers: [ + mutableTokenKey, thresholdKey.privateKeys[0], thresholdKey.privateKeys[1] ] @@ -2058,26 +2102,41 @@ describe("TokenCreateTransaction", function () { verifyTokenSupplyKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#9) Updates a mutable token with a valid key as its supply key but doesn't sign with it", async function () { + it("(#9) Updates a mutable token that doesn't have a supply key with a valid key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; + response = await JSONRPCRequest("createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + const tokenId = response.tokenId; + try { response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, + tokenId: tokenId, supplyKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); + assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); return; } @@ -2091,7 +2150,7 @@ describe("TokenCreateTransaction", function () { supplyKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2139,16 +2198,15 @@ describe("TokenCreateTransaction", function () { autoRenewAccountId: accountId, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, key ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - const tokenId = response.tokenId; - expect(accountId).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewAccountId.toString()); - expect(accountId).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_account); + const tokenInfo = await consensusInfoClient.getTokenInfo(mutableTokenId); + expect(accountId).to.equal(tokenInfo.autoRenewAccountId.toString()); }); it("(#3) Updates a mutable token with an auto renew account without signing with the account's private key", async function () { @@ -2170,7 +2228,7 @@ describe("TokenCreateTransaction", function () { autoRenewAccountId: accountId, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2190,7 +2248,7 @@ describe("TokenCreateTransaction", function () { autoRenewAccountId: "123.456.789", commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2210,7 +2268,7 @@ describe("TokenCreateTransaction", function () { autoRenewAccountId: "", commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2253,7 +2311,7 @@ describe("TokenCreateTransaction", function () { autoRenewAccountId: accountId, commonTransactionParams: { signers: [ - mutableTokenAdminKey, + mutableTokenKey, key ] } @@ -2282,7 +2340,7 @@ describe("TokenCreateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenAdminKey, + tokenId: mutableTokenId, autoRenewAccountId: accountId, commonTransactionParams: { signers: [ @@ -2328,7 +2386,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: 0, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2348,7 +2406,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: -1, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2368,7 +2426,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: 9223372036854775807n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2388,7 +2446,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: 9223372036854775806n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2408,7 +2466,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: 9223372036854775808n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2428,7 +2486,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: 18446744073709551615n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2448,7 +2506,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: 18446744073709551614n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2468,7 +2526,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: -9223372036854775808n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2488,7 +2546,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: -9223372036854775807n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2508,7 +2566,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: autoRenewPeriod, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2523,7 +2581,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: autoRenewPeriod, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2538,13 +2596,13 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: 2591999, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2558,7 +2616,7 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: autoRenewPeriod, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2573,13 +2631,13 @@ describe("TokenCreateTransaction", function () { autoRenewPeriod: 8000002, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2593,20 +2651,20 @@ describe("TokenCreateTransaction", function () { expect(expirationTime).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].expiry_timestamp); } - it("(#1) Updates an immutable token with a valid expiration time", async function () { - try { - const response = await JSONRPCRequest("updateToken", { - tokenId: immutableTokenId, - expirationTime: parseInt((Date.now() / 1000) + 5184000) - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); - return; - } - - assert.fail("Should throw an error"); - }); + //it("(#1) Updates an immutable token with a valid expiration time", async function () { + // try { + // const response = await JSONRPCRequest("updateToken", { + // tokenId: immutableTokenId, + // expirationTime: parseInt((Date.now() / 1000) + 5184000) + // }); + // if (response.status === "NOT_IMPLEMENTED") this.skip(); + // } catch (err) { + // assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + // return; + // } + // + // assert.fail("Should throw an error"); + //}); it("(#2) Updates a mutable token to an expiration time of 0", async function () { try { @@ -2615,7 +2673,7 @@ describe("TokenCreateTransaction", function () { expirationTime: 0, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2635,7 +2693,7 @@ describe("TokenCreateTransaction", function () { expirationTime: -1, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2655,7 +2713,7 @@ describe("TokenCreateTransaction", function () { expirationTime: 9223372036854775807n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2675,7 +2733,7 @@ describe("TokenCreateTransaction", function () { expirationTime: 9223372036854775806n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2695,7 +2753,7 @@ describe("TokenCreateTransaction", function () { expirationTime: 9223372036854775808n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2715,7 +2773,7 @@ describe("TokenCreateTransaction", function () { expirationTime: 18446744073709551615n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2735,7 +2793,7 @@ describe("TokenCreateTransaction", function () { expirationTime: 18446744073709551614n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2755,7 +2813,7 @@ describe("TokenCreateTransaction", function () { expirationTime: -9223372036854775808n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2775,7 +2833,7 @@ describe("TokenCreateTransaction", function () { expirationTime: -9223372036854775807n, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2788,37 +2846,37 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { - const expirationTime = parseInt((Date.now() / 1000) + 5184000); - const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, - expirationTime: expirationTime, - commonTransactionParams: { - signers: [ - mutableTokenAdminKey - ] - } - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); - }); - - it("(#12) Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { - const expirationTime = parseInt((Date.now() / 1000) + 2592000); - const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, - expirationTime: expirationTime, - commonTransactionParams: { - signers: [ - mutableTokenAdminKey - ] - } - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); - }); + //it("(#11) Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { + // const expirationTime = parseInt((Date.now() / 1000) + 5184000); + // const response = await JSONRPCRequest("updateToken", { + // tokenId: mutableTokenId, + // expirationTime: expirationTime, + // commonTransactionParams: { + // signers: [ + // mutableTokenKey + // ] + // } + // }); + // if (response.status === "NOT_IMPLEMENTED") this.skip(); + // + // verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + //}); + + //it("(#12) Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { + // const expirationTime = parseInt((Date.now() / 1000) + 2592000); + // const response = await JSONRPCRequest("updateToken", { + // tokenId: mutableTokenId, + // expirationTime: expirationTime, + // commonTransactionParams: { + // signers: [ + // mutableTokenKey + // ] + // } + // }); + // if (response.status === "NOT_IMPLEMENTED") this.skip(); + // + // verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + //}); it("(#13) Creates a token with an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { try { @@ -2827,7 +2885,7 @@ describe("TokenCreateTransaction", function () { expirationTime: parseInt((Date.now() / 1000) + 2591999), commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2847,7 +2905,7 @@ describe("TokenCreateTransaction", function () { expirationTime: expirationTime, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2863,7 +2921,7 @@ describe("TokenCreateTransaction", function () { expirationTime: 8000002, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2905,7 +2963,7 @@ describe("TokenCreateTransaction", function () { memo: memo, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2921,7 +2979,7 @@ describe("TokenCreateTransaction", function () { memo: memo, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2937,7 +2995,7 @@ describe("TokenCreateTransaction", function () { memo: memo, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -2953,7 +3011,7 @@ describe("TokenCreateTransaction", function () { memo: "This is a long memo that is not valid because it exceeds 100 characters and it should fail the test!!", commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -3012,8 +3070,7 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: publicKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -3041,8 +3098,7 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: publicKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -3070,8 +3126,7 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: privateKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -3099,7 +3154,7 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: privateKey, commonTransactionParams: { signers: [ - privateKey + mutableTokenKey ] } }); @@ -3134,11 +3189,7 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: keyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - keyList.privateKeys[0], - keyList.privateKeys[1], - keyList.privateKeys[2], - keyList.privateKeys[3] + mutableTokenKey ] } }); @@ -3193,13 +3244,7 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: nestedKeyList.key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - nestedKeyList.privateKeys[0], - nestedKeyList.privateKeys[1], - nestedKeyList.privateKeys[2], - nestedKeyList.privateKeys[3], - nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] + mutableTokenKey ] } }); @@ -3231,8 +3276,7 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: thresholdKey.key, commonTransactionParams: { signers: [ - thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] + mutableTokenKey ] } }); @@ -3241,26 +3285,41 @@ describe("TokenCreateTransaction", function () { verifyTokenFeeScheduleKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#9) Updates a mutable token with a valid key as its fee schedule key but doesn't sign with it", async function () { + it("(#9) Updates a mutable token that doesn't have a fee schedule key with a valid key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; + response = await JSONRPCRequest("createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + const tokenId = response.tokenId; + try { response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, + tokenId: tokenId, feeScheduleKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); + assert.equal(err.data.status, "TOKEN_HAS_NO_FEE_SCHEDULE_KEY"); return; } @@ -3274,7 +3333,7 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -3317,60 +3376,44 @@ describe("TokenCreateTransaction", function () { it("(#2) Updates a mutable token with a valid ED25519 public key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey", - fromKey: privateKey + type: "ed25519PublicKey" }); - const publicKey = response.key; + const key = response.key; response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - feeScheduleKey: publicKey, + feeScheduleKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenPauseKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenPauseKeyUpdate(response.tokenId, String(key).substring(24).toLowerCase()); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + type: "ecdsaSecp256k1PublicKey" }); - const publicKey = response.key; + const key = response.key; response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - feeScheduleKey: publicKey, + feeScheduleKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenPauseKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenPauseKeyUpdate(response.tokenId, String(key).substring(28).toLowerCase()); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its pause key", async function () { @@ -3391,8 +3434,7 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: privateKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -3420,7 +3462,7 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: privateKey, commonTransactionParams: { signers: [ - privateKey + mutableTokenKey ] } }); @@ -3431,7 +3473,7 @@ describe("TokenCreateTransaction", function () { }); it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { - const keyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -3448,28 +3490,25 @@ describe("TokenCreateTransaction", function () { } ] }); - if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; - const response = await JSONRPCRequest("updateToken", { + response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - feeScheduleKey: keyList.key, + feeScheduleKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - keyList.privateKeys[0], - keyList.privateKeys[1], - keyList.privateKeys[2], - keyList.privateKeys[3] + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenPauseKeyUpdate(response.tokenId, keyList.key); + verifyTokenPauseKeyUpdate(response.tokenId, key); }); it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its pause key", async function () { - const nestedKeyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -3507,30 +3546,25 @@ describe("TokenCreateTransaction", function () { } ] }); - if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; - const response = await JSONRPCRequest("updateToken", { + response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - feeScheduleKey: nestedKeyList.key, + feeScheduleKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - nestedKeyList.privateKeys[0], - nestedKeyList.privateKeys[1], - nestedKeyList.privateKeys[2], - nestedKeyList.privateKeys[3], - nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenPauseKeyUpdate(response.tokenId, nestedKeyList.key); + verifyTokenPauseKeyUpdate(response.tokenId, key); }); it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { - const thresholdKey = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -3545,43 +3579,58 @@ describe("TokenCreateTransaction", function () { } ] }); - if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; - const response = await JSONRPCRequest("updateToken", { + response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - feeScheduleKey: thresholdKey.key, + feeScheduleKey: key, commonTransactionParams: { signers: [ - thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenPauseKeyUpdate(response.tokenId, thresholdKey.key); + verifyTokenPauseKeyUpdate(response.tokenId, key); }); - it("(#9) Updates a mutable token with a valid key as its pause key but doesn't sign with it", async function () { + it("(#9) Updates a mutable token that doesn't have a pause key with a valid key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; + response = await JSONRPCRequest("createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + const tokenId = response.tokenId; + try { response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, - feeScheduleKey: key, + tokenId: tokenId, + pauseKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); + assert.equal(err.data.status, "TOKEN_HAS_NO_PAUSE_KEY"); return; } @@ -3595,7 +3644,7 @@ describe("TokenCreateTransaction", function () { feeScheduleKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -3637,7 +3686,7 @@ describe("TokenCreateTransaction", function () { metadata: metadata, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -3653,7 +3702,7 @@ describe("TokenCreateTransaction", function () { metadata: metadata, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); @@ -3692,60 +3741,44 @@ describe("TokenCreateTransaction", function () { it("(#2) Updates a mutable token with a valid ED25519 public key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey", - fromKey: privateKey + type: "ed25519PublicKey" }); - const publicKey = response.key; + const key = response.key; response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - metadataKey: publicKey, + metadataKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenMetadataKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + verifyTokenMetadataKeyUpdate(response.tokenId, String(key).substring(24).toLowerCase()); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - const privateKey = response.key; - - response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + type: "ecdsaSecp256k1PublicKey" }); - const publicKey = response.key; + const key = response.key; response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - metadataKey: publicKey, + metadataKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenMetadataKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + verifyTokenMetadataKeyUpdate(response.tokenId, String(key).substring(28).toLowerCase()); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its metadata key", async function () { @@ -3766,8 +3799,7 @@ describe("TokenCreateTransaction", function () { metadataKey: privateKey, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - privateKey + mutableTokenKey ] } }); @@ -3795,7 +3827,7 @@ describe("TokenCreateTransaction", function () { metadataKey: privateKey, commonTransactionParams: { signers: [ - privateKey + mutableTokenKey ] } }); @@ -3806,7 +3838,7 @@ describe("TokenCreateTransaction", function () { }); it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { - const keyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -3823,28 +3855,25 @@ describe("TokenCreateTransaction", function () { } ] }); - if (keyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; - const response = await JSONRPCRequest("updateToken", { + response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - metadataKey: keyList.key, + metadataKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - keyList.privateKeys[0], - keyList.privateKeys[1], - keyList.privateKeys[2], - keyList.privateKeys[3] + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMetadataKeyUpdate(response.tokenId, keyList.key); + verifyTokenMetadataKeyUpdate(response.tokenId, key); }); it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its metadata key", async function () { - const nestedKeyList = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [ { @@ -3882,30 +3911,25 @@ describe("TokenCreateTransaction", function () { } ] }); - if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; - const response = await JSONRPCRequest("updateToken", { + response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - metadataKey: nestedKeyList.key, + metadataKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey, - nestedKeyList.privateKeys[0], - nestedKeyList.privateKeys[1], - nestedKeyList.privateKeys[2], - nestedKeyList.privateKeys[3], - nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMetadataKeyUpdate(response.tokenId, nestedKeyList.key); + verifyTokenMetadataKeyUpdate(response.tokenId, key); }); it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { - const thresholdKey = await JSONRPCRequest("generateKey", { + let response = await JSONRPCRequest("generateKey", { type: "thresholdKey", threshold: 2, keys: [ @@ -3920,43 +3944,58 @@ describe("TokenCreateTransaction", function () { } ] }); - if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; - const response = await JSONRPCRequest("updateToken", { + response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - metadataKey: thresholdKey.key, + metadataKey: key, commonTransactionParams: { signers: [ - thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMetadataKeyUpdate(response.tokenId, thresholdKey.key); + verifyTokenMetadataKeyUpdate(response.tokenId, key); }); - it("(#9) Updates a mutable token with a valid key as its metadata key but doesn't sign with it", async function () { + it("(#9) Updates a mutable token that doesn't have a metadata key with a valid key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; + response = await JSONRPCRequest("createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + const tokenId = response.tokenId; + try { response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, + tokenId: tokenId, metadataKey: key, commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { - assert.equal(err.data.status, "INVALID_SIGNATURE"); + assert.equal(err.data.status, "TOKEN_HAS_NO_METADATA_KEY"); return; } @@ -3970,7 +4009,7 @@ describe("TokenCreateTransaction", function () { metadataKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { signers: [ - mutableTokenAdminKey + mutableTokenKey ] } }); From 1e7617065a534964c382992dc7a37eb92b61e329 Mon Sep 17 00:00:00 2001 From: Rob Walworth Date: Thu, 12 Sep 2024 17:37:37 -0400 Subject: [PATCH 20/25] feat: add new tests to clear out token role keys Signed-off-by: Rob Walworth --- .../test_tokenUpdateTransaction.js | 188 ++++++++++++++++-- 1 file changed, 171 insertions(+), 17 deletions(-) diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js index 0db40ca..8990194 100644 --- a/test/token-service/test_tokenUpdateTransaction.js +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -1099,7 +1099,29 @@ describe("TokenUpdateTransaction", function () { verifyTokenKycKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#9) Updates a mutable token that doesn't have a KYC key with a valid key as its KYC key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its KYC key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + kycKey: key, + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenKycKeyUpdate(response.tokenId, key); + }); + + it("(#10) Updates a mutable token that doesn't have a KYC key with a valid key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); @@ -1141,7 +1163,7 @@ describe("TokenUpdateTransaction", function () { }); - it("(#10) Updates a mutable token with an invalid key as its KYC key", async function () { + it("(#11) Updates a mutable token with an invalid key as its KYC key", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -1434,7 +1456,29 @@ describe("TokenUpdateTransaction", function () { verifyTokenFreezeKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#9) Updates a mutable token that doesn't have a freeze key with a valid key as its freeze key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its freeze key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + freezeKey: key, + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenFreezeKeyUpdate(response.tokenId, key); + }); + + it("(#10) Updates a mutable token that doesn't have a freeze key with a valid key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); @@ -1475,7 +1519,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Updates a mutable token with an invalid key as its freeze key", async function () { + it("(#11) Updates a mutable token with an invalid key as its freeze key", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -1768,7 +1812,29 @@ describe("TokenUpdateTransaction", function () { verifyTokenWipeKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#9) Updates a mutable token that doesn't have a wipe key with a valid key as its wipe key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its wipe key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + wipeKey: key, + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenWipeKeyUpdate(response.tokenId, key); + }); + + it("(#10) Updates a mutable token that doesn't have a wipe key with a valid key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); @@ -1809,7 +1875,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Updates a mutable token with an invalid key as its wipe key", async function () { + it("(#11) Updates a mutable token with an invalid key as its wipe key", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2102,7 +2168,29 @@ describe("TokenUpdateTransaction", function () { verifyTokenSupplyKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#9) Updates a mutable token that doesn't have a supply key with a valid key as its supply key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its supply key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + supplyKey: key, + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenSupplyKeyUpdate(response.tokenId, key); + }); + + it("(#10) Updates a mutable token that doesn't have a supply key with a valid key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); @@ -2143,7 +2231,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Updates a mutable token with an invalid key as its supply key", async function () { + it("(#11) Updates a mutable token with an invalid key as its supply key", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2878,7 +2966,7 @@ describe("TokenUpdateTransaction", function () { // verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); //}); - it("(#13) Creates a token with an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { + it("(#13) Updates a mutable to an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2898,7 +2986,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#14) Updates a mutable token with an expiration time 8,000,001 seconds from the current time", async function () { + it("(#14) Updates a mutable token to an expiration time 8,000,001 seconds from the current time", async function () { const expirationTime = parseInt((Date.now() / 1000) + 8000001); const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2914,7 +3002,7 @@ describe("TokenUpdateTransaction", function () { verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); }); - it("(#15) Updates a mutable token with an expiration time 8,000,002 seconds from the current time", async function () { + it("(#15) Updates a mutable token to an expiration time 8,000,002 seconds from the current time", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3285,7 +3373,29 @@ describe("TokenUpdateTransaction", function () { verifyTokenFeeScheduleKeyUpdate(response.tokenId, thresholdKey.key); }); - it("(#9) Updates a mutable token that doesn't have a fee schedule key with a valid key as its fee schedule key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its fee schedule key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: key, + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenFeeScheduleKeyUpdate(response.tokenId, key); + }); + + it("(#10) Updates a mutable token that doesn't have a fee schedule key with a valid key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); @@ -3326,7 +3436,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Updates a mutable token with an invalid key as its fee schedule key", async function () { + it("(#11) Updates a mutable token with an invalid key as its fee schedule key", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3596,7 +3706,29 @@ describe("TokenUpdateTransaction", function () { verifyTokenPauseKeyUpdate(response.tokenId, key); }); - it("(#9) Updates a mutable token that doesn't have a pause key with a valid key as its pause key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its pause key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + pauseKey: key, + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenPauseKeyUpdate(response.tokenId, key); + }); + + it("(#10) Updates a mutable token that doesn't have a pause key with a valid key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); @@ -3637,7 +3769,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Updates a mutable token with an invalid key as its pause key", async function () { + it("(#11) Updates a mutable token with an invalid key as its pause key", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3961,7 +4093,29 @@ describe("TokenUpdateTransaction", function () { verifyTokenMetadataKeyUpdate(response.tokenId, key); }); - it("(#9) Updates a mutable token that doesn't have a metadata key with a valid key as its metadata key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its metadata key", async function () { + let response = await JSONRPCRequest("generateKey", { + type: "keyList", + keys: [] + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + const key = response.key; + + response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + metadataKey: key, + commonTransactionParams: { + signers: [ + mutableTokenKey + ] + } + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + verifyTokenMetadataKeyUpdate(response.tokenId, key); + }); + + it("(#10) Updates a mutable token that doesn't have a metadata key with a valid key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey" }); @@ -4002,7 +4156,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Updates a mutable token with an invalid key as its metadata key", async function () { + it("(#11) Updates a mutable token with an invalid key as its metadata key", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, From 0114550ea5415849e6d94a94c93d564bf944e0c6 Mon Sep 17 00:00:00 2001 From: ivaylogarnev-limechain Date: Wed, 30 Oct 2024 11:24:20 +0200 Subject: [PATCH 21/25] fix: Added await to functions, compared raw key values, and aligned with the latest improvements in TokenCreateTransaction logic. Signed-off-by: ivaylogarnev-limechain --- .../test_tokenCreateTransaction.js | 2 +- .../test_tokenUpdateTransaction.js | 2532 +++++++++-------- 2 files changed, 1418 insertions(+), 1116 deletions(-) diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index 08cbae7..b8e7da9 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -25,7 +25,7 @@ BigInt.prototype.toJSON = function () { /** * Tests for TokenCreateTransaction */ -describe.only("TokenCreateTransaction", function () { +describe("TokenCreateTransaction", function () { // Tests should not take longer than 30 seconds to fully execute. this.timeout(30000); diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js index 8990194..f4b8165 100644 --- a/test/token-service/test_tokenUpdateTransaction.js +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -1,20 +1,27 @@ +import crypto from "crypto"; +import { assert, expect } from "chai"; +import { Timestamp } from "@hashgraph/sdk"; + import { JSONRPCRequest } from "../../client.js"; import mirrorNodeClient from "../../mirrorNodeClient.js"; import consensusInfoClient from "../../consensusInfoClient.js"; import { setOperator } from "../../setup_Tests.js"; -import crypto from "crypto"; -import { assert, expect } from "chai"; -import { JSONRPC } from "json-rpc-2.0"; +import { getRawKeyFromHex } from "../../utils/helpers/asn1-decoder.js"; +import { retryOnError } from "../../utils/helpers/retry-on-error.js"; +import { + getEncodedKeyHexFromKeyListConsensus, + getPublicKeyFromMirrorNode, +} from "../../utils/helpers/key.js"; // Needed to convert BigInts to JSON number format. BigInt.prototype.toJSON = function () { - return JSON.rawJSON(this.toString()) -} + return JSON.rawJSON(this.toString()); +}; /** * Tests for TokenUpdateTransaction */ -describe("TokenUpdateTransaction", function () { +describe.only("TokenUpdateTransaction", function () { // Tests should not take longer than 30 seconds to fully execute. this.timeout(30000); @@ -22,33 +29,40 @@ describe("TokenUpdateTransaction", function () { const initialTokenName = "testname"; const initialTokenSymbol = "testsymbol"; const initialTreasuryAccountId = process.env.OPERATOR_ACCOUNT_ID; - const initialSupply = 1000000; + const initialSupply = "1000000"; // Two tokens should be created. One immutable token (no admin key) and another mutable. let immutableTokenId, mutableTokenId, mutableTokenKey; - before(async function () { - await setOperator(process.env.OPERATOR_ACCOUNT_ID, process.env.OPERATOR_ACCOUNT_PRIVATE_KEY); - - // Generate an immutable key. + beforeEach(async function () { + await setOperator( + process.env.OPERATOR_ACCOUNT_ID, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + ); + + // Generate an immutable token. const response = await JSONRPCRequest("createToken", { name: initialTokenName, symbol: initialTokenSymbol, treasuryAccountId: initialTreasuryAccountId, initialSupply: initialSupply, - tokenType: "ft" + tokenType: "ft", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); + immutableTokenId = response.tokenId; await JSONRPCRequest("reset"); }); beforeEach(async function () { - await setOperator(process.env.OPERATOR_ACCOUNT_ID, process.env.OPERATOR_ACCOUNT_PRIVATE_KEY); + await setOperator( + process.env.OPERATOR_ACCOUNT_ID, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + ); let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); mutableTokenKey = response.key; @@ -68,42 +82,42 @@ describe("TokenUpdateTransaction", function () { pauseKey: mutableTokenKey, metadataKey: mutableTokenKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); mutableTokenId = response.tokenId; }); + afterEach(async function () { await JSONRPCRequest("reset"); }); describe("Token ID", function () { async function verifyTokenUpdate(tokenId) { - let mirrorNodeData = await mirrorNodeClient.getTokenData(accountId); - let consensusNodeData = await consensusInfoClient.getTokenInfo(accountId); - expect(accountId).to.be.equal(mirrorNodeData.tokens[0].token); - expect(accountId).to.be.equal(consensusNodeData.tokens.toString()); + const mirrorNodeData = await mirrorNodeClient.getTokenData(tokenId); + const consensusNodeData = await consensusInfoClient.getTokenInfo(tokenId); + + expect(tokenId).to.be.equal(mirrorNodeData.token_id); + expect(tokenId).to.be.equal(consensusNodeData.tokenId.toString()); } it("(#1) Updates an immutable token with no updates", async function () { const response = await JSONRPCRequest("updateToken", { - tokenId: immutableTokenId + tokenId: immutableTokenId, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenUpdate(response.tokenId); + await verifyTokenUpdate(response.tokenId); }); it("(#2) Updates a mutable token with no updates", async function () { const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId + tokenId: mutableTokenId, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenUpdate(response.tokenId); + await verifyTokenUpdate(response.tokenId); }); it("(#3) Updates a token with no token ID", async function () { @@ -121,15 +135,23 @@ describe("TokenUpdateTransaction", function () { describe("Symbol", function () { async function verifyTokenSymbolUpdate(tokenId, symbol) { - expect(symbol).to.equal(await consensusInfoClient.getTokenInfo(tokenId).symbol); - expect(symbol).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].symbol); + expect(symbol).to.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).symbol, + ); + expect(symbol).to.equal( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).symbol, + ); } it("(#1) Updates an immutable token with a symbol", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - symbol: "t" + symbol: "t", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -146,58 +168,56 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, symbol: symbol, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenSymbolUpdate(response.tokenId, symbol); + await retryOnError(() => + verifyTokenSymbolUpdate(response.tokenId, symbol), + ); }); it("(#3) Updates a mutable token with a symbol that is empty", async function () { - const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, - symbol: "", - commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - - // Symbol shouldn't change and should still remain as its initial value. - verifyTokenSymbolUpdate(response.tokenId, initialTokenSymbol); + const response = await JSONRPCRequest("updateToken", { + tokenId: mutableTokenId, + symbol: "", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + + // Symbol shouldn't change and should still remain as its initial value. + await verifyTokenSymbolUpdate(response.tokenId, initialTokenSymbol); }); it("(#4) Updates a mutable token with a symbol that is the maximum length", async function () { - const symbol = "This is a really long symbol but it is still valid because it is 100 characters exactly on the money" + const symbol = + "This is a really long symbol but it is still valid because it is 100 characters exactly on the money"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, symbol: symbol, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenSymbolUpdate(response.tokenId, symbol); + await retryOnError(() => + verifyTokenSymbolUpdate(response.tokenId, symbol), + ); }); it("(#5) Updates a mutable token with a symbol that exceeds the maximum length", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - symbol: "This is a long symbol that is not valid because it exceeds 100 characters and it should fail the test", + symbol: + "This is a long symbol that is not valid because it exceeds 100 characters and it should fail the test", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -212,7 +232,7 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - symbol: "t" + symbol: "t", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -226,15 +246,24 @@ describe("TokenUpdateTransaction", function () { describe("Name", function () { async function verifyTokenNameUpdate(tokenId, name) { - expect(name).to.equal(await consensusInfoClient.getTokenInfo(tokenId).name); - expect(name).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].name); + expect(name).to.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).name, + ); + + expect(name).to.equal( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).name, + ); } it("(#1) Updates an immutable token with a name", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - name: "t" + name: "t", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -251,14 +280,12 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, name: name, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenNameUpdate(response.tokenId, name); + await retryOnError(() => verifyTokenNameUpdate(response.tokenId, name)); }); it("(#3) Updates a mutable token with a name that is empty", async function () { @@ -266,31 +293,30 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, name: "", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - + // Name shouldn't change and should still remain as its initial value. - verifyTokenNameUpdate(response.tokenId, initialTokenName); + await retryOnError(() => + verifyTokenNameUpdate(response.tokenId, initialTokenName), + ); }); it("(#4) Updates a mutable token with a name that is the maximum length", async function () { - const name = "This is a really long name but it is still valid because it is 100 characters exactly on the money!!" + const name = + "This is a really long name but it is still valid because it is 100 characters exactly on the money!!"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, name: name, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenNameUpdate(response.tokenId, name); + await retryOnError(() => verifyTokenNameUpdate(response.tokenId, name)); }); it("(#5) Updates a mutable token with a name that exceeds the maximum length", async function () { @@ -299,10 +325,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, name: "This is a long name that is not valid because it exceeds 100 characters and it should fail the test!!", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -317,7 +341,7 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - name: "t" + name: "t", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -334,7 +358,7 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -347,7 +371,7 @@ describe("TokenUpdateTransaction", function () { it("(#2) Updates a mutable token with a treasury account", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -355,7 +379,7 @@ describe("TokenUpdateTransaction", function () { // Create with 1 auto token association in order to automatically associate with the created token. response = await JSONRPCRequest("createAccount", { key: key, - maxAutoTokenAssociations: 1 + maxAutoTokenAssociations: 1, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const accountId = response.accountId; @@ -364,11 +388,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, treasuryAccountId: accountId, commonTransactionParams: { - signers: [ - mutableTokenKey, - key - ] - } + signers: [mutableTokenKey, key], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -376,23 +397,31 @@ describe("TokenUpdateTransaction", function () { expect(accountId).to.equal(tokenInfo.treasuryAccountId.toString()); // Make sure the tokens were transferred from the initial treasury account to the new treasury account. - const initialTreasuryAccountBalance = await consensusInfoClient.getBalance(process.env.OPERATOR_ACCOUNT_ID); - const newTreasuryAccountBalance = await consensusInfoClient.getBalance(accountId); + const initialTreasuryAccountBalance = + await consensusInfoClient.getBalance(process.env.OPERATOR_ACCOUNT_ID); + const newTreasuryAccountBalance = + await consensusInfoClient.getBalance(accountId); assert(initialTreasuryAccountBalance.tokens._map.has(mutableTokenId)); assert(newTreasuryAccountBalance.tokens._map.has(mutableTokenId)); - expect(initialTreasuryAccountBalance.tokens._map.get(mutableTokenId).toString()).to.equal("0"); - expect(newTreasuryAccountBalance.tokens._map.get(mutableTokenId).toString()).to.equal(initialSupply.toString()); + expect( + initialTreasuryAccountBalance.tokens._map + .get(mutableTokenId) + .toString(), + ).to.equal("0"); + expect( + newTreasuryAccountBalance.tokens._map.get(mutableTokenId).toString(), + ).to.equal(initialSupply.toString()); }); it("(#3) Updates a mutable token with a treasury account without signing with the account's private key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - + response = await JSONRPCRequest("createAccount", { key: key, }); @@ -404,17 +433,15 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, treasuryAccountId: accountId, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } - + assert.fail("Should throw an error"); }); @@ -424,10 +451,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, treasuryAccountId: "123.456.789", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -440,25 +465,23 @@ describe("TokenUpdateTransaction", function () { it("(#5) Updates a mutable token with a treasury account that is deleted", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - + response = await JSONRPCRequest("createAccount", { key: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const accountId = response.accountId; - + response = await JSONRPCRequest("deleteAccount", { deleteAccountId: accountId, transferAccountId: process.env.OPERATOR_ACCOUNT_ID, commonTransactionParams: { - signers: [ - key - ] - } + signers: [key], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -467,28 +490,25 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, treasuryAccountId: accountId, commonTransactionParams: { - signers: [ - mutableTokenKey, - key - ] - } + signers: [mutableTokenKey, key], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "ACCOUNT_DELETED"); return; } - + assert.fail("Should throw an error"); }); it("(#6) Updates a mutable token with a treasury account without signing with the token's admin key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - + response = await JSONRPCRequest("createAccount", { key: key, }); @@ -500,30 +520,67 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, treasuryAccountId: accountId, commonTransactionParams: { - signers: [ - key - ] - } + signers: [key], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } - + assert.fail("Should throw an error"); }); }); describe("Admin Key", function () { - async function verifyTokenAdminKeyUpdate(tokenId, adminKey) { - expect(adminKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).adminKey.toStringDer()); - expect(adminKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].admin_key); + async function verifyTokenUpdateAdminKey(tokenId, adminKey) { + const rawKey = getRawKeyFromHex(adminKey); + + expect(rawKey).to.equal( + ( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).adminKey + ).toStringRaw(), + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "admin_key", + ); + + expect(rawKey).to.equal(publicKeyMirrorNode.toStringRaw()); + } + + async function verifyTokenUpdateWithAdminKeyList(tokenId, adminKey) { + const keyHex = await getEncodedKeyHexFromKeyListConsensus( + "getTokenInfo", + tokenId, + "adminKey", + ); + + // Consensus node check + // Removing the unnecessary prefix from the incoming key + expect(adminKey.slice(adminKey.length - keyHex.length)).to.equal(keyHex); + + // Mirror node check + const mirrorNodeKey = ( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).admin_key + ).key; + + expect(adminKey).to.equal( + // Removing the unnecessary prefix from the mirror node key + mirrorNodeKey.slice(mirrorNodeKey.length - adminKey.length), + ); } it("(#1) Updates an immutable token with a valid key as its admin key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -531,27 +588,27 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - adminKey: key + adminKey: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } - + assert.fail("Should throw an error"); }); it("(#2) Updates a mutable token with a valid ED25519 public key as its admin key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -559,28 +616,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, adminKey: publicKey, commonTransactionParams: { - signers: [ - mutableTokenKey, - privateKey - ] - } + signers: [mutableTokenKey, privateKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenAdminKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateAdminKey(response.tokenId, publicKey), + ); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its admin key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -588,28 +644,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, adminKey: publicKey, commonTransactionParams: { - signers: [ - mutableTokenKey, - privateKey - ] - } + signers: [mutableTokenKey, privateKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenAdminKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateAdminKey(response.tokenId, publicKey), + ); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its admin key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -617,28 +672,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, adminKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey, - privateKey - ] - } + signers: [mutableTokenKey, privateKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenAdminKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateAdminKey(response.tokenId, publicKey), + ); }); it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its admin key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -646,16 +700,15 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, adminKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey, - privateKey - ] - } + signers: [mutableTokenKey, privateKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenAdminKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateAdminKey(response.tokenId, publicKey), + ); }); it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { @@ -663,18 +716,18 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }, { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], }); if (keyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -687,13 +740,15 @@ describe("TokenUpdateTransaction", function () { keyList.privateKeys[0], keyList.privateKeys[1], keyList.privateKeys[2], - keyList.privateKeys[3] - ] - } + keyList.privateKeys[3], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenAdminKeyUpdate(response.tokenId, keyList.key); + await retryOnError(() => + verifyTokenUpdateWithAdminKeyList(response.tokenId, keyList.key), + ); }); it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its admin key", async function () { @@ -704,36 +759,36 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" - } - ] + type: "ecdsaSecp256k1PrivateKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], + }, + ], }); if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -748,13 +803,15 @@ describe("TokenUpdateTransaction", function () { nestedKeyList.privateKeys[2], nestedKeyList.privateKeys[3], nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + nestedKeyList.privateKeys[5], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenAdminKeyUpdate(response.tokenId, nestedKeyList.key); + await retryOnError(() => + verifyTokenUpdateWithAdminKeyList(response.tokenId, nestedKeyList.key), + ); }); it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { @@ -763,15 +820,15 @@ describe("TokenUpdateTransaction", function () { threshold: 2, keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }); if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); @@ -782,18 +839,20 @@ describe("TokenUpdateTransaction", function () { signers: [ mutableTokenKey, thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + thresholdKey.privateKeys[1], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenAdminKeyUpdate(response.tokenId, thresholdKey.key); + await retryOnError(() => + verifyTokenUpdateWithAdminKeyList(response.tokenId, thresholdKey.key), + ); }); it("(#9) Updates a mutable token with a valid key as its admin key but doesn't sign with it", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -803,10 +862,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, adminKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -823,10 +880,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, adminKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -839,14 +894,53 @@ describe("TokenUpdateTransaction", function () { }); describe("KYC Key", function () { - async function verifyTokenKycKeyUpdate(tokenId, kycKey) { - expect(kycKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).kycKey.toStringDer()); - expect(kycKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].kyc_key); + async function verifyTokenUpdateKycKey(tokenId, kycKey) { + const rawKey = getRawKeyFromHex(kycKey); + + expect(rawKey).to.equal( + ( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).kycKey + ).toStringRaw(), + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "kyc_key", + ); + + expect(rawKey).to.equal(publicKeyMirrorNode.toStringRaw()); + } + + async function verifyTokenUpdateWithKycKeyList(tokenId, kycKey) { + const keyHex = await getEncodedKeyHexFromKeyListConsensus( + "getTokenInfo", + tokenId, + "kycKey", + ); + + // Consensus node check + // Removing the unnecessary prefix from the incoming key + expect(kycKey.slice(kycKey.length - keyHex.length)).to.equal(keyHex); + + // Mirror node check + const mirrorNodeKey = ( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).kyc_key + ).key; + + expect(kycKey).to.equal( + // Removing the unnecessary prefix from the mirror node key + mirrorNodeKey.slice(mirrorNodeKey.length - kycKey.length), + ); } it("(#1) Updates an immutable token with a valid key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -854,20 +948,20 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - kycKey: key + kycKey: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } - + assert.fail("Should throw an error"); }); it("(#2) Updates a mutable token with a valid ED25519 public key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -876,20 +970,18 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, kycKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenKycKeyUpdate(response.tokenId, String(key).substring(24).toLowerCase()); + await retryOnError(() => verifyTokenUpdateKycKey(response.tokenId, key)); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -898,27 +990,25 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, kycKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenKycKeyUpdate(response.tokenId, String(key).substring(28).toLowerCase()); + await retryOnError(() => verifyTokenUpdateKycKey(response.tokenId, key)); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -926,28 +1016,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, kycKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey, - privateKey - ] - } + signers: [mutableTokenKey, privateKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenKycKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateKycKey(response.tokenId, publicKey), + ); }); it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -955,15 +1044,15 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, kycKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenKycKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateKycKey(response.tokenId, publicKey), + ); }); it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { @@ -971,18 +1060,18 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }, { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], }); if (keyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -995,13 +1084,15 @@ describe("TokenUpdateTransaction", function () { keyList.privateKeys[0], keyList.privateKeys[1], keyList.privateKeys[2], - keyList.privateKeys[3] - ] - } + keyList.privateKeys[3], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenKycKeyUpdate(response.tokenId, keyList.key); + await retryOnError(() => + verifyTokenUpdateWithKycKeyList(response.tokenId, keyList.key), + ); }); it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its KYC key", async function () { @@ -1012,36 +1103,36 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" - } - ] + type: "ecdsaSecp256k1PrivateKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], + }, + ], }); if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -1056,13 +1147,15 @@ describe("TokenUpdateTransaction", function () { nestedKeyList.privateKeys[2], nestedKeyList.privateKeys[3], nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + nestedKeyList.privateKeys[5], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenKycKeyUpdate(response.tokenId, nestedKeyList.key); + await retryOnError(() => + verifyTokenUpdateWithKycKeyList(response.tokenId, nestedKeyList.key), + ); }); it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { @@ -1071,15 +1164,15 @@ describe("TokenUpdateTransaction", function () { threshold: 2, keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }); if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); @@ -1090,40 +1183,46 @@ describe("TokenUpdateTransaction", function () { signers: [ mutableTokenKey, thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + thresholdKey.privateKeys[1], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenKycKeyUpdate(response.tokenId, thresholdKey.key); + await retryOnError(() => + verifyTokenUpdateWithKycKeyList(response.tokenId, thresholdKey.key), + ); }); - it("(#9) Updates a mutable token with an empty KeyList as its KYC key", async function () { + it.skip("(#9) Updates a mutable token with an empty KeyList as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", - keys: [] + keys: [], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; + console.log(">>", key); + response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, kycKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenKycKeyUpdate(response.tokenId, key); + console.log(key); + + await retryOnError(() => + verifyTokenUpdateWithKycKeyList(response.tokenId, key), + ); }); it("(#10) Updates a mutable token that doesn't have a KYC key with a valid key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -1136,10 +1235,8 @@ describe("TokenUpdateTransaction", function () { initialSupply: initialSupply, tokenType: "ft", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); const tokenId = response.tokenId; @@ -1148,10 +1245,8 @@ describe("TokenUpdateTransaction", function () { tokenId: tokenId, kycKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1160,7 +1255,6 @@ describe("TokenUpdateTransaction", function () { } assert.fail("Should throw an error"); - }); it("(#11) Updates a mutable token with an invalid key as its KYC key", async function () { @@ -1169,10 +1263,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, kycKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1185,14 +1277,55 @@ describe("TokenUpdateTransaction", function () { }); describe("Freeze Key", function () { - async function verifyTokenFreezeKeyUpdate(tokenId, freezeKey) { - expect(freezeKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).freezeKey.toStringDer()); - expect(freezeKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].freeze_key); + async function verifyTokenUpdateFreezeKey(tokenId, freezeKey) { + const rawKey = getRawKeyFromHex(freezeKey); + + expect(rawKey).to.equal( + ( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).freezeKey + ).toStringRaw(), + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "freeze_key", + ); + + expect(rawKey).to.equal(publicKeyMirrorNode.toStringRaw()); + } + + async function verifyTokenUpdateWithFreezeKeyList(tokenId, freezeKey) { + const keyHex = await getEncodedKeyHexFromKeyListConsensus( + "getTokenInfo", + tokenId, + "freezeKey", + ); + + // Consensus node check + // Removing the unnecessary prefix from the incoming key + expect(freezeKey.slice(freezeKey.length - keyHex.length)).to.equal( + keyHex, + ); + + // Mirror node check + const mirrorNodeKey = ( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).freeze_key + ).key; + + expect(freezeKey).to.equal( + // Removing the unnecessary prefix from the mirror node key + mirrorNodeKey.slice(mirrorNodeKey.length - freezeKey.length), + ); } it("(#1) Updates an immutable token with a valid key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -1200,27 +1333,27 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - freezeKey: key + freezeKey: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } - + assert.fail("Should throw an error"); }); it("(#2) Updates a mutable token with a valid ED25519 public key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -1228,27 +1361,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, freezeKey: publicKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenFreezeKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateFreezeKey(response.tokenId, publicKey), + ); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -1256,27 +1389,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, freezeKey: publicKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenFreezeKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateFreezeKey(response.tokenId, publicKey), + ); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -1284,27 +1417,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, freezeKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenFreezeKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateFreezeKey(response.tokenId, publicKey), + ); }); it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -1312,15 +1445,15 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, freezeKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenFreezeKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateFreezeKey(response.tokenId, publicKey), + ); }); it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { @@ -1328,18 +1461,18 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }, { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], }); if (keyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -1352,13 +1485,15 @@ describe("TokenUpdateTransaction", function () { keyList.privateKeys[0], keyList.privateKeys[1], keyList.privateKeys[2], - keyList.privateKeys[3] - ] - } + keyList.privateKeys[3], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenFreezeKeyUpdate(response.tokenId, keyList.key); + await retryOnError(() => + verifyTokenUpdateWithFreezeKeyList(response.tokenId, keyList.key), + ); }); it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its freeze key", async function () { @@ -1369,36 +1504,36 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" - } - ] + type: "ecdsaSecp256k1PrivateKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], + }, + ], }); if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -1413,13 +1548,15 @@ describe("TokenUpdateTransaction", function () { nestedKeyList.privateKeys[2], nestedKeyList.privateKeys[3], nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + nestedKeyList.privateKeys[5], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenFreezeKeyUpdate(response.tokenId, nestedKeyList.key); + await retryOnError(() => + verifyTokenUpdateWithFreezeKeyList(response.tokenId, nestedKeyList.key), + ); }); it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { @@ -1428,15 +1565,15 @@ describe("TokenUpdateTransaction", function () { threshold: 2, keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }); if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); @@ -1447,19 +1584,21 @@ describe("TokenUpdateTransaction", function () { signers: [ mutableTokenKey, thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + thresholdKey.privateKeys[1], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenFreezeKeyUpdate(response.tokenId, thresholdKey.key); + await retryOnError(() => + verifyTokenUpdateWithFreezeKeyList(response.tokenId, thresholdKey.key), + ); }); - it("(#9) Updates a mutable token with an empty KeyList as its freeze key", async function () { + it.skip("(#9) Updates a mutable token with an empty KeyList as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", - keys: [] + keys: [], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -1468,19 +1607,17 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, freezeKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenFreezeKeyUpdate(response.tokenId, key); + await verifyTokenFreezeKeyUpdate(response.tokenId, key); }); it("(#10) Updates a mutable token that doesn't have a freeze key with a valid key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -1493,10 +1630,8 @@ describe("TokenUpdateTransaction", function () { initialSupply: initialSupply, tokenType: "ft", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); const tokenId = response.tokenId; @@ -1505,10 +1640,8 @@ describe("TokenUpdateTransaction", function () { tokenId: tokenId, freezeKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1525,10 +1658,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, freezeKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1541,14 +1672,53 @@ describe("TokenUpdateTransaction", function () { }); describe("Wipe Key", function () { - async function verifyTokenWipeKeyUpdate(tokenId, wipeKey) { - expect(wipeKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).wipeKey.toStringDer()); - expect(wipeKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].wipe_key); + async function verifyTokenUpdateWipeKey(tokenId, wipeKey) { + const rawKey = getRawKeyFromHex(wipeKey); + + expect(rawKey).to.equal( + ( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).wipeKey + ).toStringRaw(), + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "wipe_key", + ); + + expect(rawKey).to.equal(publicKeyMirrorNode.toStringRaw()); + } + + async function verifyTokenUpdateWithWipeKeyList(tokenId, wipeKey) { + const keyHex = await getEncodedKeyHexFromKeyListConsensus( + "getTokenInfo", + tokenId, + "wipeKey", + ); + + // Consensus node check + // Removing the unnecessary prefix from the incoming key + expect(wipeKey.slice(wipeKey.length - keyHex.length)).to.equal(keyHex); + + // Mirror node check + const mirrorNodeKey = ( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).wipe_key + ).key; + + expect(wipeKey).to.equal( + // Removing the unnecessary prefix from the mirror node key + mirrorNodeKey.slice(mirrorNodeKey.length - wipeKey.length), + ); } it("(#1) Updates an immutable token with a valid key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -1556,27 +1726,27 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - wipeKey: key + wipeKey: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } - + assert.fail("Should throw an error"); }); it("(#2) Updates a mutable token with a valid ED25519 public key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -1584,27 +1754,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, wipeKey: publicKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenWipeKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateWipeKey(response.tokenId, publicKey), + ); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -1612,27 +1782,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, wipeKey: publicKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenWipeKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateWipeKey(response.tokenId, publicKey), + ); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -1640,27 +1810,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, wipeKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenWipeKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateWipeKey(response.tokenId, publicKey), + ); }); it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -1668,15 +1838,15 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, wipeKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenWipeKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateWipeKey(response.tokenId, publicKey), + ); }); it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { @@ -1684,18 +1854,18 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }, { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], }); if (keyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -1708,13 +1878,15 @@ describe("TokenUpdateTransaction", function () { keyList.privateKeys[0], keyList.privateKeys[1], keyList.privateKeys[2], - keyList.privateKeys[3] - ] - } + keyList.privateKeys[3], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenWipeKeyUpdate(response.tokenId, keyList.key); + await retryOnError(() => + verifyTokenUpdateWithWipeKeyList(response.tokenId, keyList.key), + ); }); it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its wipe key", async function () { @@ -1725,36 +1897,36 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" - } - ] + type: "ecdsaSecp256k1PrivateKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], + }, + ], }); if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -1769,13 +1941,15 @@ describe("TokenUpdateTransaction", function () { nestedKeyList.privateKeys[2], nestedKeyList.privateKeys[3], nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + nestedKeyList.privateKeys[5], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenWipeKeyUpdate(response.tokenId, nestedKeyList.key); + await retryOnError(() => + verifyTokenUpdateWithWipeKeyList(response.tokenId, nestedKeyList.key), + ); }); it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { @@ -1784,15 +1958,15 @@ describe("TokenUpdateTransaction", function () { threshold: 2, keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }); if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); @@ -1803,19 +1977,21 @@ describe("TokenUpdateTransaction", function () { signers: [ mutableTokenKey, thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + thresholdKey.privateKeys[1], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenWipeKeyUpdate(response.tokenId, thresholdKey.key); + await retryOnError(() => + verifyTokenUpdateWithWipeKeyList(response.tokenId, thresholdKey.key), + ); }); - it("(#9) Updates a mutable token with an empty KeyList as its wipe key", async function () { + it.skip("(#9) Updates a mutable token with an empty KeyList as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", - keys: [] + keys: [], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -1824,19 +2000,17 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, wipeKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenWipeKeyUpdate(response.tokenId, key); + await verifyTokenWipeKeyUpdate(response.tokenId, key); }); it("(#10) Updates a mutable token that doesn't have a wipe key with a valid key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -1849,10 +2023,8 @@ describe("TokenUpdateTransaction", function () { initialSupply: initialSupply, tokenType: "ft", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); const tokenId = response.tokenId; @@ -1861,10 +2033,8 @@ describe("TokenUpdateTransaction", function () { tokenId: tokenId, wipeKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1881,10 +2051,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, wipeKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -1897,14 +2065,55 @@ describe("TokenUpdateTransaction", function () { }); describe("Supply Key", function () { - async function verifyTokenSupplyKeyUpdate(tokenId, supplyKey) { - expect(supplyKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).supplyKey.toStringDer()); - expect(supplyKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].supply_key); + async function verifyTokenUpdateSupplyKey(tokenId, supplyKey) { + const rawKey = getRawKeyFromHex(supplyKey); + + expect(rawKey).to.equal( + ( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).supplyKey + ).toStringRaw(), + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "supply_key", + ); + + expect(rawKey).to.equal(publicKeyMirrorNode.toStringRaw()); + } + + async function verifyTokenUpdateWithSupplyKeyList(tokenId, supplyKey) { + const keyHex = await getEncodedKeyHexFromKeyListConsensus( + "getTokenInfo", + tokenId, + "supplyKey", + ); + + // Consensus node check + // Removing the unnecessary prefix from the incoming key + expect(supplyKey.slice(supplyKey.length - keyHex.length)).to.equal( + keyHex, + ); + + // Mirror node check + const mirrorNodeKey = ( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).supply_key + ).key; + + expect(supplyKey).to.equal( + // Removing the unnecessary prefix from the mirror node key + mirrorNodeKey.slice(mirrorNodeKey.length - supplyKey.length), + ); } it("(#1) Updates an immutable token with a valid key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -1912,27 +2121,27 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - supplyKey: key + supplyKey: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } - + assert.fail("Should throw an error"); }); it("(#2) Updates a mutable token with a valid ED25519 public key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -1940,27 +2149,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, supplyKey: publicKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenSupplyKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateSupplyKey(response.tokenId, publicKey), + ); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -1968,27 +2177,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, supplyKey: publicKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenSupplyKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateSupplyKey(response.tokenId, publicKey), + ); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -1996,27 +2205,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, supplyKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenSupplyKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateSupplyKey(response.tokenId, publicKey), + ); }); it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -2024,15 +2233,15 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, supplyKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenSupplyKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(() => + verifyTokenUpdateSupplyKey(response.tokenId, publicKey), + ); }); it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { @@ -2040,18 +2249,18 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }, { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], }); if (keyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -2064,13 +2273,15 @@ describe("TokenUpdateTransaction", function () { keyList.privateKeys[0], keyList.privateKeys[1], keyList.privateKeys[2], - keyList.privateKeys[3] - ] - } + keyList.privateKeys[3], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenSupplyKeyUpdate(response.tokenId, keyList.key); + await retryOnError(() => + verifyTokenUpdateWithSupplyKeyList(response.tokenId, keyList.key), + ); }); it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its supply key", async function () { @@ -2081,36 +2292,36 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" - } - ] + type: "ecdsaSecp256k1PrivateKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], + }, + ], }); if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -2125,13 +2336,16 @@ describe("TokenUpdateTransaction", function () { nestedKeyList.privateKeys[2], nestedKeyList.privateKeys[3], nestedKeyList.privateKeys[4], - nestedKeyList.privateKeys[5] - ] - } + nestedKeyList.privateKeys[5], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenSupplyKeyUpdate(response.tokenId, nestedKeyList.key); + await verifyTokenUpdateWithSupplyKeyList( + response.tokenId, + nestedKeyList.key, + ); }); it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { @@ -2140,15 +2354,15 @@ describe("TokenUpdateTransaction", function () { threshold: 2, keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }); if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); @@ -2159,19 +2373,21 @@ describe("TokenUpdateTransaction", function () { signers: [ mutableTokenKey, thresholdKey.privateKeys[0], - thresholdKey.privateKeys[1] - ] - } + thresholdKey.privateKeys[1], + ], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenSupplyKeyUpdate(response.tokenId, thresholdKey.key); + await retryOnError(() => + verifyTokenUpdateWithSupplyKeyList(response.tokenId, thresholdKey.key), + ); }); - it("(#9) Updates a mutable token with an empty KeyList as its supply key", async function () { + it.skip("(#9) Updates a mutable token with an empty KeyList as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", - keys: [] + keys: [], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -2180,19 +2396,17 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, supplyKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenSupplyKeyUpdate(response.tokenId, key); + await verifyTokenSupplyKeyUpdate(response.tokenId, key); }); it("(#10) Updates a mutable token that doesn't have a supply key with a valid key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -2205,10 +2419,8 @@ describe("TokenUpdateTransaction", function () { initialSupply: initialSupply, tokenType: "ft", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); const tokenId = response.tokenId; @@ -2217,10 +2429,8 @@ describe("TokenUpdateTransaction", function () { tokenId: tokenId, supplyKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2237,10 +2447,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, supplyKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2253,24 +2461,24 @@ describe("TokenUpdateTransaction", function () { }); describe("Auto Renew Account", function () { - it("(#1) Updates an immutable token with an auto renew account", async function () { - try { - const response = await JSONRPCRequest("updateToken", { - tokenId: immutableTokenId, - autoRenewAccountId: process.env.OPERATOR_ACCOUNT_ID - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); - return; - } - - assert.fail("Should throw an error"); + it("(#1) Updates an immutable token with an auto renew account", async function () { + try { + const response = await JSONRPCRequest("updateToken", { + tokenId: immutableTokenId, + autoRenewAccountId: process.env.OPERATOR_ACCOUNT_ID, + }); + if (response.status === "NOT_IMPLEMENTED") this.skip(); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); }); it("(#2) Updates a mutable token with an auto renew account", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -2285,11 +2493,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, autoRenewAccountId: accountId, commonTransactionParams: { - signers: [ - mutableTokenKey, - key - ] - } + signers: [mutableTokenKey, key], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2299,7 +2504,7 @@ describe("TokenUpdateTransaction", function () { it("(#3) Updates a mutable token with an auto renew account without signing with the account's private key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -2315,10 +2520,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, autoRenewAccountId: accountId, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2335,10 +2538,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, autoRenewAccountId: "123.456.789", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2355,10 +2556,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, autoRenewAccountId: "", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2371,7 +2570,7 @@ describe("TokenUpdateTransaction", function () { it("(#6) Updates a mutable token with an auto renew account that is deleted", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -2386,10 +2585,8 @@ describe("TokenUpdateTransaction", function () { deleteAccountId: accountId, transferAccountId: process.env.OPERATOR_ACCOUNT_ID, commonTransactionParams: { - signers: [ - key - ] - } + signers: [key], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); @@ -2398,11 +2595,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, autoRenewAccountId: accountId, commonTransactionParams: { - signers: [ - mutableTokenKey, - key - ] - } + signers: [mutableTokenKey, key], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2415,13 +2609,13 @@ describe("TokenUpdateTransaction", function () { it("(#7) Updates a mutable token with an auto renew account without signing with the token's admin key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - + response = await JSONRPCRequest("createAccount", { - key: key + key: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const accountId = response.accountId; @@ -2431,32 +2625,45 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, autoRenewAccountId: accountId, commonTransactionParams: { - signers: [ - key - ] - } + signers: [key], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } - + assert.fail("Should throw an error"); }); }); describe("Auto Renew Period", function () { async function verifyTokenAutoRenewPeriodUpdate(tokenId, autoRenewPeriod) { - expect(autoRenewPeriod).to.equal(await consensusInfoClient.getTokenInfo(tokenId).autoRenewPeriod); - expect(autoRenewPeriod).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].auto_renew_period); + expect(autoRenewPeriod).to.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).autoRenewPeriod, + ); + + expect(autoRenewPeriod).to.equal( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).auto_renew_period, + ); + + console.log( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).auto_renew_period, + ); } - - it("(#1) Updates an immutable token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { + + it("(#1) Updates an immutable token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - autoRenewPeriod: 5184000 + autoRenewPeriod: "5184000", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2471,19 +2678,17 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - autoRenewPeriod: 0, + autoRenewPeriod: "0", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); @@ -2491,19 +2696,17 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - autoRenewPeriod: -1, + autoRenewPeriod: "-1", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); @@ -2511,19 +2714,17 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - autoRenewPeriod: 9223372036854775807n, + autoRenewPeriod: "9223372036854775807", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); @@ -2531,59 +2732,53 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - autoRenewPeriod: 9223372036854775806n, + autoRenewPeriod: "9223372036854775806", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - - assert.fail("Should throw an error"); - }); - it("(#6) Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,808 (int64 max + 1) seconds", async function () { - try { - const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, - autoRenewPeriod: 9223372036854775808n, - commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); - return; - } - assert.fail("Should throw an error"); }); + // it("(#6) Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,808 (int64 max + 1) seconds", async function () { + // try { + // const response = await JSONRPCRequest("updateToken", { + // tokenId: mutableTokenId, + // autoRenewPeriod: "9223372036854775808", + // commonTransactionParams: { + // signers: [mutableTokenKey], + // }, + // }); + // if (response.status === "NOT_IMPLEMENTED") this.skip(); + // } catch (err) { + // assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); + // return; + // } + + // assert.fail("Should throw an error"); + // }); + it("(#7) Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - autoRenewPeriod: 18446744073709551615n, + autoRenewPeriod: "18446744073709551615", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); @@ -2591,39 +2786,35 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - autoRenewPeriod: 18446744073709551614n, + autoRenewPeriod: "18446744073709551614", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); - it("(#9) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + it.skip("(#9) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,808 (int64 min) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - autoRenewPeriod: -9223372036854775808n, + autoRenewPeriod: "-9223372036854775808", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); @@ -2631,62 +2822,58 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - autoRenewPeriod: -9223372036854775807n, + autoRenewPeriod: "-9223372036854775807", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } - + assert.fail("Should throw an error"); }); it("(#11) Updates a mutable token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { - const autoRenewPeriod = 5184000; + const autoRenewPeriod = "5184000"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, autoRenewPeriod: autoRenewPeriod, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); - verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); + await retryOnError(async () => { + verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); + }); }); it("(#12) Updates a mutable token with an auto renew period set to 30 days (2,592,000 seconds)", async function () { - const autoRenewPeriod = 2592000; + const autoRenewPeriod = "2592000"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, autoRenewPeriod: autoRenewPeriod, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); - verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); + await retryOnError(async () => { + verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); + }); }); it("(#13) Updates a mutable token with an auto renew period set to 30 days minus one second (2,591,999 seconds)", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - autoRenewPeriod: 2591999, + autoRenewPeriod: "2591999", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2698,30 +2885,28 @@ describe("TokenUpdateTransaction", function () { }); it("(#14) Updates a mutable token with an auto renew period set to 8,000,001 seconds", async function () { - const autoRenewPeriod = 8000001; + const autoRenewPeriod = "8000001"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, autoRenewPeriod: autoRenewPeriod, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); - verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); + await retryOnError(async () => { + verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); + }); }); it("(#15) Updates a mutable token with an auto renew period set to 8,000,002 seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - autoRenewPeriod: 8000002, + autoRenewPeriod: "8000002", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2735,11 +2920,29 @@ describe("TokenUpdateTransaction", function () { describe("Expiration Time", function () { async function verifyTokenExpirationTimeUpdate(tokenId, expirationTime) { - expect(expirationTime).to.equal(await consensusInfoClient.getTokenInfo(tokenId).expirationTime); - expect(expirationTime).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].expiry_timestamp); + const parsedExpirationTime = Timestamp.fromDate( + new Date(Number(expirationTime) * 1000), + ); + + expect(parsedExpirationTime).to.deep.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).expirationTime, + ); + + const mirrorNodeExpirationDateNanoseconds = await ( + await mirrorNodeClient.getTokenData(tokenId) + ).expiry_timestamp; + + // Convert nanoseconds got back from to timestamp + const mirrorNodeTimestamp = Timestamp.fromDate( + new Date(mirrorNodeExpirationDateNanoseconds / 1000000), + ); + + expect(parsedExpirationTime).to.deep.equal(mirrorNodeTimestamp); } - - //it("(#1) Updates an immutable token with a valid expiration time", async function () { + + //it("(#1) Updates an immutable token with a valid expiration time", async function () { // try { // const response = await JSONRPCRequest("updateToken", { // tokenId: immutableTokenId, @@ -2758,12 +2961,10 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - expirationTime: 0, + expirationTime: "0", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2778,12 +2979,10 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - expirationTime: -1, + expirationTime: "-1", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2798,12 +2997,10 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - expirationTime: 9223372036854775807n, + expirationTime: "9223372036854775807", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2818,12 +3015,10 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - expirationTime: 9223372036854775806n, + expirationTime: "9223372036854775806", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2838,12 +3033,10 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - expirationTime: 9223372036854775808n, + expirationTime: "9223372036854775808", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2858,12 +3051,10 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - expirationTime: 18446744073709551615n, + expirationTime: "18446744073709551615", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2878,12 +3069,10 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - expirationTime: 18446744073709551614n, + expirationTime: "18446744073709551614", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2898,12 +3087,10 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - expirationTime: -9223372036854775808n, + expirationTime: "-9223372036854775808", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2918,12 +3105,10 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - expirationTime: -9223372036854775807n, + expirationTime: "-9223372036854775807", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -2946,7 +3131,7 @@ describe("TokenUpdateTransaction", function () { // } // }); // if (response.status === "NOT_IMPLEMENTED") this.skip(); - // + // // verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); //}); @@ -2962,7 +3147,7 @@ describe("TokenUpdateTransaction", function () { // } // }); // if (response.status === "NOT_IMPLEMENTED") this.skip(); - // + // // verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); //}); @@ -2970,48 +3155,47 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - expirationTime: parseInt((Date.now() / 1000) + 2591999), + expirationTime: "2591999", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } - + assert.fail("Should throw an error"); }); it("(#14) Updates a mutable token to an expiration time 8,000,001 seconds from the current time", async function () { - const expirationTime = parseInt((Date.now() / 1000) + 8000001); + const expirationTime = ( + Math.floor(Date.now() / 1000) + 8000001 + ).toString(); + const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, expirationTime: expirationTime, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - - verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + + await retryOnError(async () => { + verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + }); }); it("(#15) Updates a mutable token to an expiration time 8,000,002 seconds from the current time", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, - expirationTime: 8000002, + expirationTime: "8000002", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -3025,15 +3209,24 @@ describe("TokenUpdateTransaction", function () { describe("Memo", function () { async function verifyTokenMemoUpdate(tokenId, memo) { - expect(memo).to.equal(await consensusInfoClient.getTokenInfo(tokenId).memo); - expect(memo).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].memo); + expect(memo).to.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).memo, + ); + + expect(memo).to.equal( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).memo, + ); } - - it("(#1) Updates an immutable token with a memo that is a valid length", async function () { + + it("(#1) Updates an immutable token with a memo that is a valid length", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - memo: "testmemo" + memo: "testmemo", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -3045,51 +3238,52 @@ describe("TokenUpdateTransaction", function () { }); it("(#2) Updates a mutable token with a memo that is a valid length", async function () { - const memo = "testmemo" + const memo = "testmemo"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, memo: memo, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMemoUpdate(response.tokenId, memo); + await retryOnError(async () => { + verifyTokenMemoUpdate(response.tokenId, memo); + }); }); it("(#3) Updates a mutable token with a memo that is the minimum length", async function () { - const memo = "" + const memo = ""; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, memo: memo, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMemoUpdate(response.tokenId, memo); + await retryOnError(async () => { + verifyTokenMemoUpdate(response.tokenId, memo); + }); }); it("(#4) Updates a mutable token with a memo that is the minimum length", async function () { - const memo = "This is a really long memo but it is still valid because it is 100 characters exactly on the money!!" + const memo = + "This is a really long memo but it is still valid because it is 100 characters exactly on the money!!"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, memo: memo, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMemoUpdate(response.tokenId, memo); + await retryOnError(async () => { + verifyTokenMemoUpdate(response.tokenId, memo); + }); }); it("(#5) Updates a mutable token with a memo that exceeds the maximum length", async function () { @@ -3098,10 +3292,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, memo: "This is a long memo that is not valid because it exceeds 100 characters and it should fail the test!!", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -3114,14 +3306,58 @@ describe("TokenUpdateTransaction", function () { }); describe("Fee Schedule Key", function () { - async function verifyTokenFeeScheduleKeyUpdate(tokenId, feeScheduleKey) { - expect(feeScheduleKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).feeScheduleKey.toStringDer()); - expect(feeScheduleKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].fee_schedule_key); + async function verifyTokenUpdateFeeScheduleKey(tokenId, feeScheduleKey) { + const rawKey = getRawKeyFromHex(feeScheduleKey); + + expect(rawKey).to.equal( + ( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).feeScheduleKey + ).toStringRaw(), + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "fee_schedule_key", + ); + + expect(rawKey).to.equal(publicKeyMirrorNode.toStringRaw()); + } + + async function verifyTokenUpdateWithFeeScheduleKeyList( + tokenId, + feeScheduleKey, + ) { + const keyHex = await getEncodedKeyHexFromKeyListConsensus( + "getTokenInfo", + tokenId, + "feeScheduleKey", + ); + + // Consensus node check + // Removing the unnecessary prefix from the incoming key + expect( + feeScheduleKey.slice(feeScheduleKey.length - keyHex.length), + ).to.equal(keyHex); + + // Mirror node check + const mirrorNodeKey = ( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).fee_schedule_key + ).key; + + expect(feeScheduleKey).to.equal( + // Removing the unnecessary prefix from the mirror node key + mirrorNodeKey.slice(mirrorNodeKey.length - feeScheduleKey.length), + ); } it("(#1) Updates an immutable token with a valid key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -3129,27 +3365,27 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - feeScheduleKey: key + feeScheduleKey: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } - + assert.fail("Should throw an error"); }); it("(#2) Updates a mutable token with a valid ED25519 public key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -3157,27 +3393,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: publicKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenFeeScheduleKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdateFeeScheduleKey(response.tokenId, publicKey); + }); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -3185,27 +3421,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: publicKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenFeeScheduleKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdateFeeScheduleKey(response.tokenId, publicKey); + }); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -3213,27 +3449,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenFeeScheduleKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdateFeeScheduleKey(response.tokenId, publicKey); + }); }); it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -3241,15 +3477,15 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenFeeScheduleKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdateFeeScheduleKey(response.tokenId, publicKey); + }); }); it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { @@ -3257,18 +3493,18 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }, { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], }); if (keyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -3276,14 +3512,14 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: keyList.key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenFeeScheduleKeyUpdate(response.tokenId, keyList.key); + await retryOnError(async () => { + verifyTokenUpdateWithFeeScheduleKeyList(response.tokenId, keyList.key); + }); }); it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its fee schedule key", async function () { @@ -3294,36 +3530,36 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" - } - ] + type: "ecdsaSecp256k1PrivateKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], + }, + ], }); if (nestedKeyList.status === "NOT_IMPLEMENTED") this.skip(); @@ -3331,14 +3567,17 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: nestedKeyList.key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenFeeScheduleKeyUpdate(response.tokenId, nestedKeyList.key); + await retryOnError(async () => { + verifyTokenUpdateWithFeeScheduleKeyList( + response.tokenId, + nestedKeyList.key, + ); + }); }); it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { @@ -3347,15 +3586,15 @@ describe("TokenUpdateTransaction", function () { threshold: 2, keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }); if (thresholdKey.status === "NOT_IMPLEMENTED") this.skip(); @@ -3363,20 +3602,23 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: thresholdKey.key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenFeeScheduleKeyUpdate(response.tokenId, thresholdKey.key); + await retryOnError(async () => { + verifyTokenUpdateWithFeeScheduleKeyList( + response.tokenId, + thresholdKey.key, + ); + }); }); - it("(#9) Updates a mutable token with an empty KeyList as its fee schedule key", async function () { + it.skip("(#9) Updates a mutable token with an empty KeyList as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", - keys: [] + keys: [], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -3385,19 +3627,17 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenFeeScheduleKeyUpdate(response.tokenId, key); + await verifyTokenFeeScheduleKeyUpdate(response.tokenId, key); }); it("(#10) Updates a mutable token that doesn't have a fee schedule key with a valid key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -3410,10 +3650,8 @@ describe("TokenUpdateTransaction", function () { initialSupply: initialSupply, tokenType: "ft", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); const tokenId = response.tokenId; @@ -3422,10 +3660,8 @@ describe("TokenUpdateTransaction", function () { tokenId: tokenId, feeScheduleKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -3442,10 +3678,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -3458,14 +3692,53 @@ describe("TokenUpdateTransaction", function () { }); describe("Pause Key", function () { - async function verifyTokenPauseKeyUpdate(tokenId, pauseKey) { - expect(pauseKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).pauseKey.toStringDer()); - expect(pauseKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].pause_key); + async function verifyTokenUpdatePauseKey(tokenId, pauseKey) { + const rawKey = getRawKeyFromHex(pauseKey); + + expect(rawKey).to.equal( + ( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).pauseKey + ).toStringRaw(), + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "pause_key", + ); + + expect(rawKey).to.equal(publicKeyMirrorNode.toStringRaw()); + } + + async function verifyTokenUpdateWithPauseKeyList(tokenId, pauseKey) { + const keyHex = await getEncodedKeyHexFromKeyListConsensus( + "getTokenInfo", + tokenId, + "pauseKey", + ); + + // Consensus node check + // Removing the unnecessary prefix from the incoming key + expect(pauseKey.slice(pauseKey.length - keyHex.length)).to.equal(keyHex); + + // Mirror node check + const mirrorNodeKey = ( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).pause_key + ).key; + + expect(pauseKey).to.equal( + // Removing the unnecessary prefix from the mirror node key + mirrorNodeKey.slice(mirrorNodeKey.length - pauseKey.length), + ); } it("(#1) Updates an immutable token with a valid key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -3473,20 +3746,20 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - feeScheduleKey: key + feeScheduleKey: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } - + assert.fail("Should throw an error"); }); it("(#2) Updates a mutable token with a valid ED25519 public key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }); const key = response.key; @@ -3494,20 +3767,20 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenPauseKeyUpdate(response.tokenId, String(key).substring(24).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdatePauseKey(response.tokenId, key); + }); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }); const key = response.key; @@ -3515,27 +3788,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenPauseKeyUpdate(response.tokenId, String(key).substring(28).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdatePauseKey(response.tokenId, key); + }); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -3543,27 +3816,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenPauseKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdatePauseKey(response.tokenId, publicKey); + }); }); it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -3571,15 +3844,15 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenPauseKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdatePauseKey(response.tokenId, publicKey); + }); }); it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { @@ -3587,18 +3860,18 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }, { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -3607,14 +3880,14 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenPauseKeyUpdate(response.tokenId, key); + await retryOnError(async () => { + verifyTokenUpdateWithPauseKeyList(response.tokenId, key); + }); }); it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its pause key", async function () { @@ -3625,36 +3898,36 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" - } - ] + type: "ecdsaSecp256k1PrivateKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], + }, + ], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -3663,14 +3936,14 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenPauseKeyUpdate(response.tokenId, key); + await retryOnError(async () => { + verifyTokenUpdateWithPauseKeyList(response.tokenId, key); + }); }); it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { @@ -3679,15 +3952,15 @@ describe("TokenUpdateTransaction", function () { threshold: 2, keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -3696,20 +3969,20 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenPauseKeyUpdate(response.tokenId, key); + await retryOnError(async () => { + verifyTokenUpdateWithPauseKeyList(response.tokenId, key); + }); }); - it("(#9) Updates a mutable token with an empty KeyList as its pause key", async function () { + it.skip("(#9) Updates a mutable token with an empty KeyList as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", - keys: [] + keys: [], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -3718,19 +3991,17 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, pauseKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenPauseKeyUpdate(response.tokenId, key); + await verifyTokenPauseKeyUpdate(response.tokenId, key); }); it("(#10) Updates a mutable token that doesn't have a pause key with a valid key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -3743,10 +4014,8 @@ describe("TokenUpdateTransaction", function () { initialSupply: initialSupply, tokenType: "ft", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); const tokenId = response.tokenId; @@ -3755,10 +4024,8 @@ describe("TokenUpdateTransaction", function () { tokenId: tokenId, pauseKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -3775,10 +4042,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, feeScheduleKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -3792,15 +4057,19 @@ describe("TokenUpdateTransaction", function () { describe("Metadata", function () { async function verifyTokenMetadataUpdate(tokenId, metadata) { - expect(metadata).to.equal(await consensusInfoClient.getTokenInfo(tokenId).metadata); - expect(metadata).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].metadata); + expect(metadata).to.equal( + await consensusInfoClient.getTokenInfo(tokenId).metadata, + ); + expect(metadata).to.equal( + await mirrorNodeClient.getTokenData(tokenId).tokens[0].metadata, + ); } - - it("(#1) Updates an immutable token with metadata", async function () { + + it("(#1) Updates an immutable token with metadata", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - metadata: "1234" + metadata: "1234", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -3817,14 +4086,14 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, metadata: metadata, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMetadataUpdate(response.tokenId, metadata); + await retryOnError(async () => { + verifyTokenMetadataUpdate(response.tokenId, metadata); + }); }); it("(#3) Updates a mutable token with empty metadata", async function () { @@ -3833,26 +4102,67 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, metadata: metadata, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMetadataUpdate(response.tokenId, metadata); + await retryOnError(async () => { + verifyTokenMetadataUpdate(response.tokenId, metadata); + }); }); }); describe("Metadata Key", function () { - async function verifyTokenMetadataKeyUpdate(tokenId, metadataKey) { - expect(metadataKey).to.equal(await consensusInfoClient.getTokenInfo(tokenId).metadataKey.toStringDer()); - expect(metadataKey).to.equal(await mirrorNodeClient.getTokenData(tokenId).tokens[0].metadata_key); + async function verifyTokenUpdateMetadataKey(tokenId, pauseKey) { + const rawKey = getRawKeyFromHex(pauseKey); + + expect(rawKey).to.equal( + ( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).pauseKey + ).toStringRaw(), + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "metadata_key", + ); + + expect(rawKey).to.equal(publicKeyMirrorNode.toStringRaw()); + } + + async function verifyTokenUpdateWithMetadataKeyList(tokenId, metadataKey) { + const keyHex = await getEncodedKeyHexFromKeyListConsensus( + "getTokenInfo", + tokenId, + "metadataKey", + ); + + // Consensus node check + // Removing the unnecessary prefix from the incoming key + expect(metadataKey.slice(metadataKey.length - keyHex.length)).to.equal( + keyHex, + ); + + // Mirror node check + const mirrorNodeKey = ( + await ( + await mirrorNodeClient.getTokenData(tokenId) + ).metadata_key + ).key; + + expect(metadataKey).to.equal( + // Removing the unnecessary prefix from the mirror node key + mirrorNodeKey.slice(mirrorNodeKey.length - metadataKey.length), + ); } it("(#1) Updates an immutable token with a valid key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -3860,20 +4170,20 @@ describe("TokenUpdateTransaction", function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: immutableTokenId, - metadataKey: key + metadataKey: key, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } - + assert.fail("Should throw an error"); }); it("(#2) Updates a mutable token with a valid ED25519 public key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }); const key = response.key; @@ -3881,20 +4191,20 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, metadataKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenMetadataKeyUpdate(response.tokenId, String(key).substring(24).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdateMetadataKey(response.tokenId, key); + }); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }); const key = response.key; @@ -3902,27 +4212,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, metadataKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenMetadataKeyUpdate(response.tokenId, String(key).substring(28).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdateMetadataKey(response.tokenId, key); + }); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -3930,27 +4240,27 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, metadataKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - verifyTokenMetadataKeyUpdate(response.tokenId, String(publicKey).substring(24).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdateMetadataKey(response.tokenId, publicKey); + }); }); it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const privateKey = response.key; response = await JSONRPCRequest("generateKey", { type: "ecdsaSecp256k1PublicKey", - fromKey: privateKey + fromKey: privateKey, }); const publicKey = response.key; @@ -3958,15 +4268,15 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, metadataKey: privateKey, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - verifyTokenMetadataKeyUpdate(response.tokenId, String(publicKey).substring(28).toLowerCase()); + await retryOnError(async () => { + verifyTokenUpdateMetadataKey(response.tokenId, publicKey); + }); }); it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { @@ -3974,18 +4284,18 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ed25519PublicKey" + type: "ed25519PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" + type: "ecdsaSecp256k1PrivateKey", }, { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -3994,14 +4304,14 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, metadataKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMetadataKeyUpdate(response.tokenId, key); + await retryOnError(async () => { + verifyTokenUpdateWithMetadataKeyList(response.tokenId, key); + }); }); it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its metadata key", async function () { @@ -4012,36 +4322,36 @@ describe("TokenUpdateTransaction", function () { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ecdsaSecp256k1PrivateKey" - } - ] + type: "ecdsaSecp256k1PrivateKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }, { type: "keyList", keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" - } - ] - } - ] + type: "ecdsaSecp256k1PublicKey", + }, + ], + }, + ], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -4050,14 +4360,14 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, metadataKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMetadataKeyUpdate(response.tokenId, key); + await retryOnError(async () => { + verifyTokenUpdateWithMetadataKeyList(response.tokenId, key); + }); }); it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { @@ -4066,15 +4376,15 @@ describe("TokenUpdateTransaction", function () { threshold: 2, keys: [ { - type: "ed25519PrivateKey" + type: "ed25519PrivateKey", }, { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }, { - type: "ed25519PublicKey" - } - ] + type: "ed25519PublicKey", + }, + ], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -4083,20 +4393,20 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, metadataKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMetadataKeyUpdate(response.tokenId, key); + await retryOnError(async () => { + verifyTokenUpdateWithMetadataKeyList(response.tokenId, key); + }); }); - it("(#9) Updates a mutable token with an empty KeyList as its metadata key", async function () { + it.skip("(#9) Updates a mutable token with an empty KeyList as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", - keys: [] + keys: [], }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -4105,19 +4415,17 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, metadataKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - verifyTokenMetadataKeyUpdate(response.tokenId, key); + await verifyTokenMetadataKeyUpdate(response.tokenId, key); }); it("(#10) Updates a mutable token that doesn't have a metadata key with a valid key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { - type: "ecdsaSecp256k1PublicKey" + type: "ecdsaSecp256k1PublicKey", }); if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; @@ -4130,10 +4438,8 @@ describe("TokenUpdateTransaction", function () { initialSupply: initialSupply, tokenType: "ft", commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); const tokenId = response.tokenId; @@ -4142,10 +4448,8 @@ describe("TokenUpdateTransaction", function () { tokenId: tokenId, metadataKey: key, commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { @@ -4162,10 +4466,8 @@ describe("TokenUpdateTransaction", function () { tokenId: mutableTokenId, metadataKey: crypto.randomBytes(88).toString("hex"), commonTransactionParams: { - signers: [ - mutableTokenKey - ] - } + signers: [mutableTokenKey], + }, }); if (response.status === "NOT_IMPLEMENTED") this.skip(); } catch (err) { From 1ffb4bf20aa12f75939f1eca9e22df09bfe27b6d Mon Sep 17 00:00:00 2001 From: ivaylogarnev-limechain Date: Wed, 30 Oct 2024 13:55:55 +0200 Subject: [PATCH 22/25] fix: Deleted int64 + 1 tests in both docs/tests code Signed-off-by: ivaylogarnev-limechain --- .../token-service/tokenUpdateTransaction.md | 42 ++++++----- .../test_tokenUpdateTransaction.js | 72 +++++-------------- 2 files changed, 38 insertions(+), 76 deletions(-) diff --git a/test-specifications/token-service/tokenUpdateTransaction.md b/test-specifications/token-service/tokenUpdateTransaction.md index 2178e8c..7a186fb 100644 --- a/test-specifications/token-service/tokenUpdateTransaction.md +++ b/test-specifications/token-service/tokenUpdateTransaction.md @@ -509,17 +509,16 @@ The tests contained in this specification will assume that two valid token were | 2 | Updates a mutable token with an auto renew period set to 0 seconds | tokenId=, autoRenewPeriod=0, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | | 3 | Updates a mutable token with an auto renew period set to -1 seconds | tokenId=, autoRenewPeriod=-1, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | | 4 | Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,807 (int64 max) seconds | tokenId=, autoRenewPeriod=9223372036854775807, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 5 | Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,806 (int64 max - 1) seconds | tokenId=, autoRenewPeriod=9223372036854775806, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 6 | Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,808 (int64 max + 1) seconds | tokenId=, autoRenewPeriod=9223372036854775808, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 7 | Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,615 (uint64 max) seconds | tokenId=, autoRenewPeriod=18446744073709551615, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 8 | Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,614 (uint64 max - 1) seconds | tokenId=, autoRenewPeriod=18446744073709551614, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 9 | Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,808 (int64 min) seconds | tokenId=, autoRenewPeriod=-9223372036854775808, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 10 | Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,8087 (int64 min + 1) seconds | tokenId=, autoRenewPeriod=-9223372036854775807, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 11 | Updates a mutable token with an auto renew period set to 60 days (5,184,000 seconds) | tokenId=, autoRenewPeriod=5184000, commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 5,184,000 seconds. | N | -| 12 | Updates a mutable token with an auto renew period set to 30 days (2,592,000 seconds) | tokenId=, autoRenewPeriod=2592000, commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 2,592,000 seconds. | N | -| 13 | Updates a mutable token with an auto renew period set to 30 days minus one second (2,591,999 seconds) | tokenId=, autoRenewPeriod=2591999, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 14 | Updates a mutable token with an auto renew period set to 8,000,001 seconds | tokenId=, autoRenewPeriod=8000001, commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 8,000,001 seconds. | N | -| 15 | Updates a mutable token with an auto renew period set to 8,000,002 seconds | tokenId=, autoRenewPeriod=8000002, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 5 | Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,806 (int64 max - 1) seconds | tokenId=, autoRenewPeriod=9223372036854775806, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | | +| 6 | Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,615 (uint64 max) seconds | tokenId=, autoRenewPeriod=18446744073709551615, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 7 | Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,614 (uint64 max - 1) seconds | tokenId=, autoRenewPeriod=18446744073709551614, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 8 | Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,808 (int64 min) seconds | tokenId=, autoRenewPeriod=-9223372036854775808, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 9 | Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,8087 (int64 min + 1) seconds | tokenId=, autoRenewPeriod=-9223372036854775807, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 10 | Updates a mutable token with an auto renew period set to 60 days (5,184,000 seconds) | tokenId=, autoRenewPeriod=5184000, commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 5,184,000 seconds. | N | +| 11 | Updates a mutable token with an auto renew period set to 30 days (2,592,000 seconds) | tokenId=, autoRenewPeriod=2592000, commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 2,592,000 seconds. | N | +| 12 | Updates a mutable token with an auto renew period set to 30 days minus one second (2,591,999 seconds) | tokenId=, autoRenewPeriod=2591999, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 13 | Updates a mutable token with an auto renew period set to 8,000,001 seconds | tokenId=, autoRenewPeriod=8000001, commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 8,000,001 seconds. | N | +| 14 | Updates a mutable token with an auto renew period set to 8,000,002 seconds | tokenId=, autoRenewPeriod=8000002, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | #### JSON Request Example @@ -557,17 +556,16 @@ The tests contained in this specification will assume that two valid token were | 2 | Updates a mutable token to an expiration time of 0 | tokenId=, expirationTime=0, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | | 3 | Updates a mutable token to an expiration time of -1 | tokenId=, expirationTime=-1, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | | 4 | Updates a mutable token to an expiration time of 9,223,372,036,854,775,807 (int64 max) seconds | tokenId=, expirationTime=9223372036854775807, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 5 | Updates a mutable token to an expiration time of 9,223,372,036,854,775,806 (int64 max - 1) seconds | tokenId=, expirationTime=9223372036854775806, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 6 | Updates a mutable token to an expiration time of 9,223,372,036,854,775,808 (int64 max + 1) seconds | tokenId=, expirationTime=9223372036854775808, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 7 | Updates a mutable token to an expiration time of 18,446,744,073,709,551,615 (uint64 max) seconds | tokenId=, expirationTime=18446744073709551615, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 8 | Updates a mutable token to an expiration time of 18,446,744,073,709,551,614 (uint64 max - 1) seconds | tokenId=, expirationTime=18446744073709551614, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 9 | Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds | tokenId=, expirationTime=-9223372036854775808, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 10 | Updates a mutable token to an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds | tokenId=, expirationTime=-9223372036854775807, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 11 | Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time | tokenId=, expirationTime= + 5184000, commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 5,184,000 seconds (60 days) from the current epoch time. | N | -| 12 | Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time | tokenId=, expirationTime= + 2592000, commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 2,592,000 seconds (30 days) from the current epoch time. | N | -| 13 | Updates a mutable token to an expiration time of 30 days minus one second (2,591,999 seconds) from the current time | tokenId=, expirationTime= + 2591999, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 14 | Updates a mutable token with an expiration time 8,000,001 seconds from the current time | tokenId=, expirationTime= + 8000001, commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 8,000,001 from the current epoch time. | N | -| 15 | Updates a mutable token with an expiration time 8,000,002 seconds from the current time | tokenId=, expirationTime= + 8000002, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 5 | Updates a mutable token to an expiration time of 9,223,372,036,854,775,806 (int64 max - 1) seconds | tokenId=, expirationTime=9223372036854775806, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | | N | +| 6 | Updates a mutable token to an expiration time of 18,446,744,073,709,551,615 (uint64 max) seconds | tokenId=, expirationTime=18446744073709551615, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 7 | Updates a mutable token to an expiration time of 18,446,744,073,709,551,614 (uint64 max - 1) seconds | tokenId=, expirationTime=18446744073709551614, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 8 | Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds | tokenId=, expirationTime=-9223372036854775808, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 9 | Updates a mutable token to an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds | tokenId=, expirationTime=-9223372036854775807, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 10 | Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time | tokenId=, expirationTime= + 5184000, commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 5,184,000 seconds (60 days) from the current epoch time. | N | +| 11 | Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time | tokenId=, expirationTime= + 2592000, commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 2,592,000 seconds (30 days) from the current epoch time. | N | +| 12 | Updates a mutable token to an expiration time of 30 days minus one second (2,591,999 seconds) from the current time | tokenId=, expirationTime= + 2591999, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 13 | Updates a mutable token with an expiration time 8,000,001 seconds from the current time | tokenId=, expirationTime= + 8000001, commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 8,000,001 from the current epoch time. | N | +| 14 | Updates a mutable token with an expiration time 8,000,002 seconds from the current time | tokenId=, expirationTime= + 8000002, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | #### JSON Request Example diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js index f4b8165..e04b9ba 100644 --- a/test/token-service/test_tokenUpdateTransaction.js +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -2746,25 +2746,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - // it("(#6) Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,808 (int64 max + 1) seconds", async function () { - // try { - // const response = await JSONRPCRequest("updateToken", { - // tokenId: mutableTokenId, - // autoRenewPeriod: "9223372036854775808", - // commonTransactionParams: { - // signers: [mutableTokenKey], - // }, - // }); - // if (response.status === "NOT_IMPLEMENTED") this.skip(); - // } catch (err) { - // assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); - // return; - // } - - // assert.fail("Should throw an error"); - // }); - - it("(#7) Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { + it("(#6) Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2782,7 +2764,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#8) Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,614 (uint64 max - 1) seconds", async function () { + it("(#7) Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,614 (uint64 max - 1) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2800,7 +2782,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#9) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + it.skip("(#8) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,808 (int64 min) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2818,7 +2800,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { + it("(#9) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2836,7 +2818,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) Updates a mutable token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { + it("(#10) Updates a mutable token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { const autoRenewPeriod = "5184000"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2851,7 +2833,7 @@ describe.only("TokenUpdateTransaction", function () { }); }); - it("(#12) Updates a mutable token with an auto renew period set to 30 days (2,592,000 seconds)", async function () { + it("(#11) Updates a mutable token with an auto renew period set to 30 days (2,592,000 seconds)", async function () { const autoRenewPeriod = "2592000"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2866,7 +2848,7 @@ describe.only("TokenUpdateTransaction", function () { }); }); - it("(#13) Updates a mutable token with an auto renew period set to 30 days minus one second (2,591,999 seconds)", async function () { + it("(#12) Updates a mutable token with an auto renew period set to 30 days minus one second (2,591,999 seconds)", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2884,7 +2866,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#14) Updates a mutable token with an auto renew period set to 8,000,001 seconds", async function () { + it("(#13) Updates a mutable token with an auto renew period set to 8,000,001 seconds", async function () { const autoRenewPeriod = "8000001"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2899,7 +2881,7 @@ describe.only("TokenUpdateTransaction", function () { }); }); - it("(#15) Updates a mutable token with an auto renew period set to 8,000,002 seconds", async function () { + it("(#14) Updates a mutable token with an auto renew period set to 8,000,002 seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3029,25 +3011,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Updates a mutable token to an expiration time of 9,223,372,036,854,775,808 (int64 max + 1) seconds", async function () { - try { - const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, - expirationTime: "9223372036854775808", - commonTransactionParams: { - signers: [mutableTokenKey], - }, - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#7) Updates a mutable token to an expiration time of 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { + it("(#6) Updates a mutable token to an expiration time of 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3065,7 +3029,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#8) Updates a mutable token to an expiration time of 18,446,744,073,709,551,614 (uint64 max - 1) seconds", async function () { + it("(#7) Updates a mutable token to an expiration time of 18,446,744,073,709,551,614 (uint64 max - 1) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3083,7 +3047,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#9) Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + it("(#8) Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3101,7 +3065,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Updates a mutable token to an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { + it("(#9) Updates a mutable token to an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3119,7 +3083,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - //it("(#11) Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { + //it("(#10) Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { // const expirationTime = parseInt((Date.now() / 1000) + 5184000); // const response = await JSONRPCRequest("updateToken", { // tokenId: mutableTokenId, @@ -3135,7 +3099,7 @@ describe.only("TokenUpdateTransaction", function () { // verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); //}); - //it("(#12) Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { + //it("(#11) Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { // const expirationTime = parseInt((Date.now() / 1000) + 2592000); // const response = await JSONRPCRequest("updateToken", { // tokenId: mutableTokenId, @@ -3151,7 +3115,7 @@ describe.only("TokenUpdateTransaction", function () { // verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); //}); - it("(#13) Updates a mutable to an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { + it("(#12) Updates a mutable to an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3169,7 +3133,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#14) Updates a mutable token to an expiration time 8,000,001 seconds from the current time", async function () { + it("(#13) Updates a mutable token to an expiration time 8,000,001 seconds from the current time", async function () { const expirationTime = ( Math.floor(Date.now() / 1000) + 8000001 ).toString(); @@ -3188,7 +3152,7 @@ describe.only("TokenUpdateTransaction", function () { }); }); - it("(#15) Updates a mutable token to an expiration time 8,000,002 seconds from the current time", async function () { + it("(#14) Updates a mutable token to an expiration time 8,000,002 seconds from the current time", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, From 06b68b0e01119dce296f775fbd4b02ffb3dac070 Mon Sep 17 00:00:00 2001 From: ivaylogarnev-limechain Date: Wed, 30 Oct 2024 15:27:50 +0200 Subject: [PATCH 23/25] fix: Added tests for empty KeyList as prop for a key Signed-off-by: ivaylogarnev-limechain --- .../test_tokenUpdateTransaction.js | 164 +++++++++++++++--- utils/helpers/key.js | 4 + 2 files changed, 143 insertions(+), 25 deletions(-) diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js index e04b9ba..5bcd48d 100644 --- a/test/token-service/test_tokenUpdateTransaction.js +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -938,6 +938,22 @@ describe.only("TokenUpdateTransaction", function () { ); } + async function verifyTokenUpdateWithNullKycKey(tokenId) { + expect(null).to.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).kycKey, + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "kyc_key", + ); + + expect(null).to.equal(publicKeyMirrorNode); + } + it("(#1) Updates an immutable token with a valid key as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", @@ -1194,7 +1210,7 @@ describe.only("TokenUpdateTransaction", function () { ); }); - it.skip("(#9) Updates a mutable token with an empty KeyList as its KYC key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its KYC key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [], @@ -1202,8 +1218,6 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); const key = response.key; - console.log(">>", key); - response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, kycKey: key, @@ -1213,10 +1227,8 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - console.log(key); - - await retryOnError(() => - verifyTokenUpdateWithKycKeyList(response.tokenId, key), + await retryOnError(async () => + verifyTokenUpdateWithNullKycKey(response.tokenId, key), ); }); @@ -1323,6 +1335,22 @@ describe.only("TokenUpdateTransaction", function () { ); } + async function verifyTokenUpdateWithNullFreezeKey(tokenId) { + expect(null).to.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).freezeKey, + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "freeze_key", + ); + + expect(null).to.equal(publicKeyMirrorNode); + } + it("(#1) Updates an immutable token with a valid key as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", @@ -1595,7 +1623,7 @@ describe.only("TokenUpdateTransaction", function () { ); }); - it.skip("(#9) Updates a mutable token with an empty KeyList as its freeze key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its freeze key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [], @@ -1612,7 +1640,9 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await verifyTokenFreezeKeyUpdate(response.tokenId, key); + await retryOnError(async () => + verifyTokenUpdateWithNullFreezeKey(response.tokenId), + ); }); it("(#10) Updates a mutable token that doesn't have a freeze key with a valid key as its freeze key", async function () { @@ -1716,6 +1746,22 @@ describe.only("TokenUpdateTransaction", function () { ); } + async function verifyTokenUpdateWithNullWipeKey(tokenId) { + expect(null).to.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).wipeKey, + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "wipe_key", + ); + + expect(null).to.equal(publicKeyMirrorNode); + } + it("(#1) Updates an immutable token with a valid key as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", @@ -1988,7 +2034,7 @@ describe.only("TokenUpdateTransaction", function () { ); }); - it.skip("(#9) Updates a mutable token with an empty KeyList as its wipe key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its wipe key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [], @@ -2005,7 +2051,9 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await verifyTokenWipeKeyUpdate(response.tokenId, key); + await retryOnError(async () => + verifyTokenUpdateWithNullWipeKey(response.tokenId), + ); }); it("(#10) Updates a mutable token that doesn't have a wipe key with a valid key as its wipe key", async function () { @@ -2111,6 +2159,22 @@ describe.only("TokenUpdateTransaction", function () { ); } + async function verifyTokenUpdateWithNullFeeScheduleKey(tokenId) { + expect(null).to.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).supplyKey, + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "supply_key", + ); + + expect(null).to.equal(publicKeyMirrorNode); + } + it("(#1) Updates an immutable token with a valid key as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", @@ -2384,7 +2448,7 @@ describe.only("TokenUpdateTransaction", function () { ); }); - it.skip("(#9) Updates a mutable token with an empty KeyList as its supply key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its supply key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [], @@ -2401,7 +2465,9 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await verifyTokenSupplyKeyUpdate(response.tokenId, key); + await retryOnError(async () => { + verifyTokenUpdateWithNullFeeScheduleKey(response.tokenId); + }); }); it("(#10) Updates a mutable token that doesn't have a supply key with a valid key as its supply key", async function () { @@ -2651,12 +2717,6 @@ describe.only("TokenUpdateTransaction", function () { await mirrorNodeClient.getTokenData(tokenId) ).auto_renew_period, ); - - console.log( - await ( - await mirrorNodeClient.getTokenData(tokenId) - ).auto_renew_period, - ); } it("(#1) Updates an immutable token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { @@ -3319,6 +3379,22 @@ describe.only("TokenUpdateTransaction", function () { ); } + async function verifyTokenUpdateWithNullFeeScheduleKey(tokenId) { + expect(null).to.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).feeScheduleKey, + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "fee_schedule_key", + ); + + expect(null).to.equal(publicKeyMirrorNode); + } + it("(#1) Updates an immutable token with a valid key as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", @@ -3579,7 +3655,7 @@ describe.only("TokenUpdateTransaction", function () { }); }); - it.skip("(#9) Updates a mutable token with an empty KeyList as its fee schedule key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its fee schedule key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [], @@ -3596,7 +3672,9 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await verifyTokenFeeScheduleKeyUpdate(response.tokenId, key); + await retryOnError(async () => { + verifyTokenUpdateWithNullFeeScheduleKey(response.tokenId); + }); }); it("(#10) Updates a mutable token that doesn't have a fee schedule key with a valid key as its fee schedule key", async function () { @@ -3700,6 +3778,22 @@ describe.only("TokenUpdateTransaction", function () { ); } + async function verifyTokenUpdateWithNullPauseKey(tokenId) { + expect(null).to.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).pauseKey, + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "pause_key", + ); + + expect(null).to.equal(publicKeyMirrorNode); + } + it("(#1) Updates an immutable token with a valid key as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", @@ -3943,7 +4037,7 @@ describe.only("TokenUpdateTransaction", function () { }); }); - it.skip("(#9) Updates a mutable token with an empty KeyList as its pause key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its pause key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [], @@ -3960,7 +4054,9 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await verifyTokenPauseKeyUpdate(response.tokenId, key); + await retryOnError(async () => { + await verifyTokenUpdateWithNullPauseKey(response.tokenId); + }); }); it("(#10) Updates a mutable token that doesn't have a pause key with a valid key as its pause key", async function () { @@ -4124,6 +4220,22 @@ describe.only("TokenUpdateTransaction", function () { ); } + async function verifyTokenUpdateWithNullMetadataKey(tokenId) { + expect(null).to.equal( + await ( + await consensusInfoClient.getTokenInfo(tokenId) + ).metadataKey, + ); + + const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + "metadata_key", + ); + + expect(null).to.equal(publicKeyMirrorNode); + } + it("(#1) Updates an immutable token with a valid key as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { type: "ed25519PublicKey", @@ -4367,7 +4479,7 @@ describe.only("TokenUpdateTransaction", function () { }); }); - it.skip("(#9) Updates a mutable token with an empty KeyList as its metadata key", async function () { + it("(#9) Updates a mutable token with an empty KeyList as its metadata key", async function () { let response = await JSONRPCRequest("generateKey", { type: "keyList", keys: [], @@ -4384,7 +4496,9 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await verifyTokenMetadataKeyUpdate(response.tokenId, key); + await retryOnError(async () => { + verifyTokenUpdateWithNullMetadataKey(response.tokenId); + }); }); it("(#10) Updates a mutable token that doesn't have a metadata key with a valid key as its metadata key", async function () { diff --git a/utils/helpers/key.js b/utils/helpers/key.js index 75ffdd2..578a4e3 100644 --- a/utils/helpers/key.js +++ b/utils/helpers/key.js @@ -57,6 +57,10 @@ export const getPublicKeyFromMirrorNode = async ( // Access the dynamic key (e.g., fee_schedule_key, admin_key, etc.) const keyMirrorNode = data[searchedKey]; + if (keyMirrorNode == null) { + return null; + } + // Use the appropriate key type function to convert the key const publicKeyMirrorNode = keyTypeConvertFunctions[keyMirrorNode._type]( keyMirrorNode.key, From 638b745e20633117ca3a01841ef1cee30e911158 Mon Sep 17 00:00:00 2001 From: ivaylogarnev-limechain Date: Thu, 31 Oct 2024 09:52:30 +0200 Subject: [PATCH 24/25] refactor: Removed retrieving the tokenID from response logic Signed-off-by: ivaylogarnev-limechain --- .../test_tokenUpdateTransaction.js | 164 +++++++++--------- 1 file changed, 80 insertions(+), 84 deletions(-) diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js index 5bcd48d..e9d4df1 100644 --- a/test/token-service/test_tokenUpdateTransaction.js +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -108,7 +108,7 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await verifyTokenUpdate(response.tokenId); + await verifyTokenUpdate(immutableTokenId); }); it("(#2) Updates a mutable token with no updates", async function () { @@ -117,7 +117,7 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await verifyTokenUpdate(response.tokenId); + await verifyTokenUpdate(mutableTokenId); }); it("(#3) Updates a token with no token ID", async function () { @@ -173,9 +173,7 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await retryOnError(() => - verifyTokenSymbolUpdate(response.tokenId, symbol), - ); + await retryOnError(() => verifyTokenSymbolUpdate(mutableTokenId, symbol)); }); it("(#3) Updates a mutable token with a symbol that is empty", async function () { @@ -189,7 +187,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); // Symbol shouldn't change and should still remain as its initial value. - await verifyTokenSymbolUpdate(response.tokenId, initialTokenSymbol); + await verifyTokenSymbolUpdate(mutableTokenId, initialTokenSymbol); }); it("(#4) Updates a mutable token with a symbol that is the maximum length", async function () { @@ -204,9 +202,7 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await retryOnError(() => - verifyTokenSymbolUpdate(response.tokenId, symbol), - ); + await retryOnError(() => verifyTokenSymbolUpdate(mutableTokenId, symbol)); }); it("(#5) Updates a mutable token with a symbol that exceeds the maximum length", async function () { @@ -285,7 +281,7 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await retryOnError(() => verifyTokenNameUpdate(response.tokenId, name)); + await retryOnError(() => verifyTokenNameUpdate(mutableTokenId, name)); }); it("(#3) Updates a mutable token with a name that is empty", async function () { @@ -300,7 +296,7 @@ describe.only("TokenUpdateTransaction", function () { // Name shouldn't change and should still remain as its initial value. await retryOnError(() => - verifyTokenNameUpdate(response.tokenId, initialTokenName), + verifyTokenNameUpdate(mutableTokenId, initialTokenName), ); }); @@ -316,7 +312,7 @@ describe.only("TokenUpdateTransaction", function () { }); if (response.status === "NOT_IMPLEMENTED") this.skip(); - await retryOnError(() => verifyTokenNameUpdate(response.tokenId, name)); + await retryOnError(() => verifyTokenNameUpdate(mutableTokenId, name)); }); it("(#5) Updates a mutable token with a name that exceeds the maximum length", async function () { @@ -623,7 +619,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(() => - verifyTokenUpdateAdminKey(response.tokenId, publicKey), + verifyTokenUpdateAdminKey(mutableTokenId, publicKey), ); }); @@ -651,7 +647,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(() => - verifyTokenUpdateAdminKey(response.tokenId, publicKey), + verifyTokenUpdateAdminKey(mutableTokenId, publicKey), ); }); @@ -679,7 +675,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(() => - verifyTokenUpdateAdminKey(response.tokenId, publicKey), + verifyTokenUpdateAdminKey(mutableTokenId, publicKey), ); }); @@ -707,7 +703,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(() => - verifyTokenUpdateAdminKey(response.tokenId, publicKey), + verifyTokenUpdateAdminKey(mutableTokenId, publicKey), ); }); @@ -747,7 +743,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithAdminKeyList(response.tokenId, keyList.key), + verifyTokenUpdateWithAdminKeyList(mutableTokenId, keyList.key), ); }); @@ -810,7 +806,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithAdminKeyList(response.tokenId, nestedKeyList.key), + verifyTokenUpdateWithAdminKeyList(mutableTokenId, nestedKeyList.key), ); }); @@ -846,7 +842,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithAdminKeyList(response.tokenId, thresholdKey.key), + verifyTokenUpdateWithAdminKeyList(mutableTokenId, thresholdKey.key), ); }); @@ -992,7 +988,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. - await retryOnError(() => verifyTokenUpdateKycKey(response.tokenId, key)); + await retryOnError(() => verifyTokenUpdateKycKey(mutableTokenId, key)); }); it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its KYC key", async function () { @@ -1012,7 +1008,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. - await retryOnError(() => verifyTokenUpdateKycKey(response.tokenId, key)); + await retryOnError(() => verifyTokenUpdateKycKey(mutableTokenId, key)); }); it("(#4) Updates a mutable token with a valid ED25519 private key as its KYC key", async function () { @@ -1039,7 +1035,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(() => - verifyTokenUpdateKycKey(response.tokenId, publicKey), + verifyTokenUpdateKycKey(mutableTokenId, publicKey), ); }); @@ -1067,7 +1063,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(() => - verifyTokenUpdateKycKey(response.tokenId, publicKey), + verifyTokenUpdateKycKey(mutableTokenId, publicKey), ); }); @@ -1107,7 +1103,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithKycKeyList(response.tokenId, keyList.key), + verifyTokenUpdateWithKycKeyList(mutableTokenId, keyList.key), ); }); @@ -1170,7 +1166,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithKycKeyList(response.tokenId, nestedKeyList.key), + verifyTokenUpdateWithKycKeyList(mutableTokenId, nestedKeyList.key), ); }); @@ -1206,7 +1202,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithKycKeyList(response.tokenId, thresholdKey.key), + verifyTokenUpdateWithKycKeyList(mutableTokenId, thresholdKey.key), ); }); @@ -1228,7 +1224,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => - verifyTokenUpdateWithNullKycKey(response.tokenId, key), + verifyTokenUpdateWithNullKycKey(mutableTokenId, key), ); }); @@ -1396,7 +1392,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(() => - verifyTokenUpdateFreezeKey(response.tokenId, publicKey), + verifyTokenUpdateFreezeKey(mutableTokenId, publicKey), ); }); @@ -1424,7 +1420,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(() => - verifyTokenUpdateFreezeKey(response.tokenId, publicKey), + verifyTokenUpdateFreezeKey(mutableTokenId, publicKey), ); }); @@ -1452,7 +1448,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(() => - verifyTokenUpdateFreezeKey(response.tokenId, publicKey), + verifyTokenUpdateFreezeKey(mutableTokenId, publicKey), ); }); @@ -1480,7 +1476,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(() => - verifyTokenUpdateFreezeKey(response.tokenId, publicKey), + verifyTokenUpdateFreezeKey(mutableTokenId, publicKey), ); }); @@ -1520,7 +1516,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithFreezeKeyList(response.tokenId, keyList.key), + verifyTokenUpdateWithFreezeKeyList(mutableTokenId, keyList.key), ); }); @@ -1583,7 +1579,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithFreezeKeyList(response.tokenId, nestedKeyList.key), + verifyTokenUpdateWithFreezeKeyList(mutableTokenId, nestedKeyList.key), ); }); @@ -1619,7 +1615,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithFreezeKeyList(response.tokenId, thresholdKey.key), + verifyTokenUpdateWithFreezeKeyList(mutableTokenId, thresholdKey.key), ); }); @@ -1641,7 +1637,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => - verifyTokenUpdateWithNullFreezeKey(response.tokenId), + verifyTokenUpdateWithNullFreezeKey(mutableTokenId), ); }); @@ -1807,7 +1803,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(() => - verifyTokenUpdateWipeKey(response.tokenId, publicKey), + verifyTokenUpdateWipeKey(mutableTokenId, publicKey), ); }); @@ -1835,7 +1831,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(() => - verifyTokenUpdateWipeKey(response.tokenId, publicKey), + verifyTokenUpdateWipeKey(mutableTokenId, publicKey), ); }); @@ -1863,7 +1859,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(() => - verifyTokenUpdateWipeKey(response.tokenId, publicKey), + verifyTokenUpdateWipeKey(mutableTokenId, publicKey), ); }); @@ -1891,7 +1887,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(() => - verifyTokenUpdateWipeKey(response.tokenId, publicKey), + verifyTokenUpdateWipeKey(mutableTokenId, publicKey), ); }); @@ -1931,7 +1927,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithWipeKeyList(response.tokenId, keyList.key), + verifyTokenUpdateWithWipeKeyList(mutableTokenId, keyList.key), ); }); @@ -1994,7 +1990,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithWipeKeyList(response.tokenId, nestedKeyList.key), + verifyTokenUpdateWithWipeKeyList(mutableTokenId, nestedKeyList.key), ); }); @@ -2030,7 +2026,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithWipeKeyList(response.tokenId, thresholdKey.key), + verifyTokenUpdateWithWipeKeyList(mutableTokenId, thresholdKey.key), ); }); @@ -2052,7 +2048,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => - verifyTokenUpdateWithNullWipeKey(response.tokenId), + verifyTokenUpdateWithNullWipeKey(mutableTokenId), ); }); @@ -2220,7 +2216,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(() => - verifyTokenUpdateSupplyKey(response.tokenId, publicKey), + verifyTokenUpdateSupplyKey(mutableTokenId, publicKey), ); }); @@ -2248,7 +2244,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(() => - verifyTokenUpdateSupplyKey(response.tokenId, publicKey), + verifyTokenUpdateSupplyKey(mutableTokenId, publicKey), ); }); @@ -2276,7 +2272,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(() => - verifyTokenUpdateSupplyKey(response.tokenId, publicKey), + verifyTokenUpdateSupplyKey(mutableTokenId, publicKey), ); }); @@ -2304,7 +2300,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(() => - verifyTokenUpdateSupplyKey(response.tokenId, publicKey), + verifyTokenUpdateSupplyKey(mutableTokenId, publicKey), ); }); @@ -2344,7 +2340,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithSupplyKeyList(response.tokenId, keyList.key), + verifyTokenUpdateWithSupplyKeyList(mutableTokenId, keyList.key), ); }); @@ -2407,7 +2403,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await verifyTokenUpdateWithSupplyKeyList( - response.tokenId, + mutableTokenId, nestedKeyList.key, ); }); @@ -2444,7 +2440,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(() => - verifyTokenUpdateWithSupplyKeyList(response.tokenId, thresholdKey.key), + verifyTokenUpdateWithSupplyKeyList(mutableTokenId, thresholdKey.key), ); }); @@ -2466,7 +2462,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenUpdateWithNullFeeScheduleKey(response.tokenId); + verifyTokenUpdateWithNullFeeScheduleKey(mutableTokenId); }); }); @@ -2889,7 +2885,7 @@ describe.only("TokenUpdateTransaction", function () { }); await retryOnError(async () => { - verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); + verifyTokenAutoRenewPeriodUpdate(mutableTokenId, autoRenewPeriod); }); }); @@ -2904,7 +2900,7 @@ describe.only("TokenUpdateTransaction", function () { }); await retryOnError(async () => { - verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); + verifyTokenAutoRenewPeriodUpdate(mutableTokenId, autoRenewPeriod); }); }); @@ -2937,7 +2933,7 @@ describe.only("TokenUpdateTransaction", function () { }); await retryOnError(async () => { - verifyTokenAutoRenewPeriodUpdate(response.tokenId, autoRenewPeriod); + verifyTokenAutoRenewPeriodUpdate(mutableTokenId, autoRenewPeriod); }); }); @@ -3208,7 +3204,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + verifyTokenExpirationTimeUpdate(mutableTokenId, expirationTime); }); }); @@ -3273,7 +3269,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenMemoUpdate(response.tokenId, memo); + verifyTokenMemoUpdate(mutableTokenId, memo); }); }); @@ -3289,7 +3285,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenMemoUpdate(response.tokenId, memo); + verifyTokenMemoUpdate(mutableTokenId, memo); }); }); @@ -3306,7 +3302,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenMemoUpdate(response.tokenId, memo); + verifyTokenMemoUpdate(mutableTokenId, memo); }); }); @@ -3440,7 +3436,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(async () => { - verifyTokenUpdateFeeScheduleKey(response.tokenId, publicKey); + verifyTokenUpdateFeeScheduleKey(mutableTokenId, publicKey); }); }); @@ -3468,7 +3464,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(async () => { - verifyTokenUpdateFeeScheduleKey(response.tokenId, publicKey); + verifyTokenUpdateFeeScheduleKey(mutableTokenId, publicKey); }); }); @@ -3496,7 +3492,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(async () => { - verifyTokenUpdateFeeScheduleKey(response.tokenId, publicKey); + verifyTokenUpdateFeeScheduleKey(mutableTokenId, publicKey); }); }); @@ -3524,7 +3520,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(async () => { - verifyTokenUpdateFeeScheduleKey(response.tokenId, publicKey); + verifyTokenUpdateFeeScheduleKey(mutableTokenId, publicKey); }); }); @@ -3558,7 +3554,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenUpdateWithFeeScheduleKeyList(response.tokenId, keyList.key); + verifyTokenUpdateWithFeeScheduleKeyList(mutableTokenId, keyList.key); }); }); @@ -3614,7 +3610,7 @@ describe.only("TokenUpdateTransaction", function () { await retryOnError(async () => { verifyTokenUpdateWithFeeScheduleKeyList( - response.tokenId, + mutableTokenId, nestedKeyList.key, ); }); @@ -3649,7 +3645,7 @@ describe.only("TokenUpdateTransaction", function () { await retryOnError(async () => { verifyTokenUpdateWithFeeScheduleKeyList( - response.tokenId, + mutableTokenId, thresholdKey.key, ); }); @@ -3673,7 +3669,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenUpdateWithNullFeeScheduleKey(response.tokenId); + verifyTokenUpdateWithNullFeeScheduleKey(mutableTokenId); }); }); @@ -3832,7 +3828,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(async () => { - verifyTokenUpdatePauseKey(response.tokenId, key); + verifyTokenUpdatePauseKey(mutableTokenId, key); }); }); @@ -3853,7 +3849,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(async () => { - verifyTokenUpdatePauseKey(response.tokenId, key); + verifyTokenUpdatePauseKey(mutableTokenId, key); }); }); @@ -3881,7 +3877,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(async () => { - verifyTokenUpdatePauseKey(response.tokenId, publicKey); + verifyTokenUpdatePauseKey(mutableTokenId, publicKey); }); }); @@ -3909,7 +3905,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(async () => { - verifyTokenUpdatePauseKey(response.tokenId, publicKey); + verifyTokenUpdatePauseKey(mutableTokenId, publicKey); }); }); @@ -3944,7 +3940,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenUpdateWithPauseKeyList(response.tokenId, key); + verifyTokenUpdateWithPauseKeyList(mutableTokenId, key); }); }); @@ -4000,7 +3996,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenUpdateWithPauseKeyList(response.tokenId, key); + verifyTokenUpdateWithPauseKeyList(mutableTokenId, key); }); }); @@ -4033,7 +4029,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenUpdateWithPauseKeyList(response.tokenId, key); + verifyTokenUpdateWithPauseKeyList(mutableTokenId, key); }); }); @@ -4055,7 +4051,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - await verifyTokenUpdateWithNullPauseKey(response.tokenId); + await verifyTokenUpdateWithNullPauseKey(mutableTokenId); }); }); @@ -4152,7 +4148,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenMetadataUpdate(response.tokenId, metadata); + verifyTokenMetadataUpdate(mutableTokenId, metadata); }); }); @@ -4168,7 +4164,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenMetadataUpdate(response.tokenId, metadata); + verifyTokenMetadataUpdate(mutableTokenId, metadata); }); }); }); @@ -4274,7 +4270,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(async () => { - verifyTokenUpdateMetadataKey(response.tokenId, key); + verifyTokenUpdateMetadataKey(mutableTokenId, key); }); }); @@ -4295,7 +4291,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(async () => { - verifyTokenUpdateMetadataKey(response.tokenId, key); + verifyTokenUpdateMetadataKey(mutableTokenId, key); }); }); @@ -4323,7 +4319,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. await retryOnError(async () => { - verifyTokenUpdateMetadataKey(response.tokenId, publicKey); + verifyTokenUpdateMetadataKey(mutableTokenId, publicKey); }); }); @@ -4351,7 +4347,7 @@ describe.only("TokenUpdateTransaction", function () { // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. await retryOnError(async () => { - verifyTokenUpdateMetadataKey(response.tokenId, publicKey); + verifyTokenUpdateMetadataKey(mutableTokenId, publicKey); }); }); @@ -4386,7 +4382,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenUpdateWithMetadataKeyList(response.tokenId, key); + verifyTokenUpdateWithMetadataKeyList(mutableTokenId, key); }); }); @@ -4442,7 +4438,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenUpdateWithMetadataKeyList(response.tokenId, key); + verifyTokenUpdateWithMetadataKeyList(mutableTokenId, key); }); }); @@ -4475,7 +4471,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenUpdateWithMetadataKeyList(response.tokenId, key); + verifyTokenUpdateWithMetadataKeyList(mutableTokenId, key); }); }); @@ -4497,7 +4493,7 @@ describe.only("TokenUpdateTransaction", function () { if (response.status === "NOT_IMPLEMENTED") this.skip(); await retryOnError(async () => { - verifyTokenUpdateWithNullMetadataKey(response.tokenId); + verifyTokenUpdateWithNullMetadataKey(mutableTokenId); }); }); From e22b5610680666ab71554a3d6b73738f92ad6214 Mon Sep 17 00:00:00 2001 From: ivaylogarnev-limechain Date: Fri, 1 Nov 2024 20:07:45 +0200 Subject: [PATCH 25/25] fix: Removed all uint64 tests both in docs and in js, removed unneccesary prototype change and removed .only Signed-off-by: ivaylogarnev-limechain --- .../token-service/tokenUpdateTransaction.md | 60 +++++----- .../test_tokenCreateTransaction.js | 5 - .../test_tokenUpdateTransaction.js | 107 +++--------------- 3 files changed, 43 insertions(+), 129 deletions(-) diff --git a/test-specifications/token-service/tokenUpdateTransaction.md b/test-specifications/token-service/tokenUpdateTransaction.md index 7a186fb..55d9b17 100644 --- a/test-specifications/token-service/tokenUpdateTransaction.md +++ b/test-specifications/token-service/tokenUpdateTransaction.md @@ -42,8 +42,8 @@ https://docs.hedera.com/hedera/sdks-and-apis/rest-api | wipeKey | string | optional | The desired new wipe key of the token. DER-encoded hex string representation for private or public keys. Keylists and threshold keys are the hex of the serialized protobuf bytes. | | supplyKey | string | optional | The desired new supply key of the token. DER-encoded hex string representation for private or public keys. Keylists and threshold keys are the hex of the serialized protobuf bytes. | | autoRenewAccountId | string | optional | The ID of the desired account to now pay auto-renewal fees. | -| autoRenewPeriod | int64 | optional | The desired new interval of time for which to charge the auto-renew account to renew the token. Units of seconds. | -| expirationTime | int64 | optional | The desired new expiration time of the token. Epoch time in seconds. | +| autoRenewPeriod | string | optional | The desired new interval of time for which to charge the auto-renew account to renew the token. Units of seconds. | +| expirationTime | string | optional | The desired new expiration time of the token. Epoch time in seconds. | | memo | string | optional | The desired new memo of the token. | | feeScheduleKey | string | optional | The desired new fee schedule key of the token. DER-encoded hex string representation for private or public keys. Keylists and threshold keys are the hex of the serialized protobuf bytes. | | pauseKey | string | optional | The desired new pause key of the token. DER-encoded hex string representation for private or public keys. Keylists and threshold keys are the hex of the serialized protobuf bytes. | @@ -505,20 +505,18 @@ The tests contained in this specification will assume that two valid token were | Test no | Name | Input | Expected response | Implemented (Y/N) | |---------|--------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|-------------------| -| 1 | Updates an immutable token with an auto renew period set to 60 days (5,184,000 seconds) | tokenId=, autoRenewPeriod=5184000 | The token update fails with a TOKEN_IS_IMMUTABLE response code from the network. | N | -| 2 | Updates a mutable token with an auto renew period set to 0 seconds | tokenId=, autoRenewPeriod=0, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 3 | Updates a mutable token with an auto renew period set to -1 seconds | tokenId=, autoRenewPeriod=-1, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 4 | Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,807 (int64 max) seconds | tokenId=, autoRenewPeriod=9223372036854775807, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 5 | Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,806 (int64 max - 1) seconds | tokenId=, autoRenewPeriod=9223372036854775806, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | | -| 6 | Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,615 (uint64 max) seconds | tokenId=, autoRenewPeriod=18446744073709551615, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 7 | Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,614 (uint64 max - 1) seconds | tokenId=, autoRenewPeriod=18446744073709551614, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 8 | Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,808 (int64 min) seconds | tokenId=, autoRenewPeriod=-9223372036854775808, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 9 | Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,8087 (int64 min + 1) seconds | tokenId=, autoRenewPeriod=-9223372036854775807, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 10 | Updates a mutable token with an auto renew period set to 60 days (5,184,000 seconds) | tokenId=, autoRenewPeriod=5184000, commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 5,184,000 seconds. | N | -| 11 | Updates a mutable token with an auto renew period set to 30 days (2,592,000 seconds) | tokenId=, autoRenewPeriod=2592000, commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 2,592,000 seconds. | N | -| 12 | Updates a mutable token with an auto renew period set to 30 days minus one second (2,591,999 seconds) | tokenId=, autoRenewPeriod=2591999, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | -| 13 | Updates a mutable token with an auto renew period set to 8,000,001 seconds | tokenId=, autoRenewPeriod=8000001, commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 8,000,001 seconds. | N | -| 14 | Updates a mutable token with an auto renew period set to 8,000,002 seconds | tokenId=, autoRenewPeriod=8000002, commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 1 | Updates an immutable token with an auto renew period set to 60 days (5,184,000 seconds) | tokenId=, autoRenewPeriod="5184000" | The token update fails with a TOKEN_IS_IMMUTABLE response code from the network. | N | +| 2 | Updates a mutable token with an auto renew period set to 0 seconds | tokenId=, autoRenewPeriod="0", commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 3 | Updates a mutable token with an auto renew period set to -1 seconds | tokenId=, autoRenewPeriod="-1", commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 4 | Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,807 (int64 max) seconds | tokenId=, autoRenewPeriod="9223372036854775807", commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 5 | Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,806 (int64 max - 1) seconds | tokenId=, autoRenewPeriod="9223372036854775806", commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | | | +| 6 | Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,808 (int64 min) seconds | tokenId=, autoRenewPeriod="-9223372036854775808", commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 7 | Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,8087 (int64 min + 1) seconds | tokenId=, autoRenewPeriod="-9223372036854775807", commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 8 | Updates a mutable token with an auto renew period set to 60 days (5,184,000 seconds) | tokenId=, autoRenewPeriod="5184000", commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 5,184,000 seconds. | N | +| 9 | Updates a mutable token with an auto renew period set to 30 days (2,592,000 seconds) | tokenId=, autoRenewPeriod="2592000", commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 2,592,000 seconds. | N | +| 10 | Updates a mutable token with an auto renew period set to 30 days minus one second (2,591,999 seconds) | tokenId=, autoRenewPeriod="2591999", commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | +| 11 | Updates a mutable token with an auto renew period set to 8,000,001 seconds | tokenId=, autoRenewPeriod="8000001", commonTransactionParams.signers=[] | The token update succeeds and the token's auto renew period equals 8,000,001 seconds. | N | +| 12 | Updates a mutable token with an auto renew period set to 8,000,002 seconds | tokenId=, autoRenewPeriod="8000002", commonTransactionParams.signers=[] | The token update fails with an INVALID_RENEWAL_PERIOD response code from the network. | N | #### JSON Request Example @@ -529,7 +527,7 @@ The tests contained in this specification will assume that two valid token were "method": "updateToken", "params": { "tokenId": "0.0.853", - "autoRenewPeriod": 5184000 + "autoRenewPeriod": "5184000" } } ``` @@ -552,20 +550,18 @@ The tests contained in this specification will assume that two valid token were | Test no | Name | Input | Expected response | Implemented (Y/N) | |---------|---------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|-------------------| -| 1 | Updates an immutable token with a valid expiration time | tokenId=, expirationTime= + 5184000 | The token update fails with a TOKEN_IS_IMMUTABLE response code from the network. | N | -| 2 | Updates a mutable token to an expiration time of 0 | tokenId=, expirationTime=0, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 3 | Updates a mutable token to an expiration time of -1 | tokenId=, expirationTime=-1, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 4 | Updates a mutable token to an expiration time of 9,223,372,036,854,775,807 (int64 max) seconds | tokenId=, expirationTime=9223372036854775807, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 5 | Updates a mutable token to an expiration time of 9,223,372,036,854,775,806 (int64 max - 1) seconds | tokenId=, expirationTime=9223372036854775806, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | | N | -| 6 | Updates a mutable token to an expiration time of 18,446,744,073,709,551,615 (uint64 max) seconds | tokenId=, expirationTime=18446744073709551615, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 7 | Updates a mutable token to an expiration time of 18,446,744,073,709,551,614 (uint64 max - 1) seconds | tokenId=, expirationTime=18446744073709551614, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 8 | Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds | tokenId=, expirationTime=-9223372036854775808, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 9 | Updates a mutable token to an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds | tokenId=, expirationTime=-9223372036854775807, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 10 | Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time | tokenId=, expirationTime= + 5184000, commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 5,184,000 seconds (60 days) from the current epoch time. | N | -| 11 | Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time | tokenId=, expirationTime= + 2592000, commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 2,592,000 seconds (30 days) from the current epoch time. | N | -| 12 | Updates a mutable token to an expiration time of 30 days minus one second (2,591,999 seconds) from the current time | tokenId=, expirationTime= + 2591999, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | -| 13 | Updates a mutable token with an expiration time 8,000,001 seconds from the current time | tokenId=, expirationTime= + 8000001, commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 8,000,001 from the current epoch time. | N | -| 14 | Updates a mutable token with an expiration time 8,000,002 seconds from the current time | tokenId=, expirationTime= + 8000002, commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 1 | Updates an immutable token with a valid expiration time | tokenId=, expirationTime= + "5184000" | The token update fails with a TOKEN_IS_IMMUTABLE response code from the network. | N | +| 2 | Updates a mutable token to an expiration time of 0 | tokenId=, expirationTime="0", commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 3 | Updates a mutable token to an expiration time of -1 | tokenId=, expirationTime="-1", commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 4 | Updates a mutable token to an expiration time of 9,223,372,036,854,775,807 (int64 max) seconds | tokenId=, expirationTime="9223372036854775807", commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 5 | Updates a mutable token to an expiration time of 9,223,372,036,854,775,806 (int64 max - 1) seconds | tokenId=, expirationTime="9223372036854775806", commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | | N | | N | +| 6 | Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds | tokenId=, expirationTime="-9223372036854775808", commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 7 | Updates a mutable token to an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds | tokenId=, expirationTime="-9223372036854775807", commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 8 | Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time | tokenId=, expirationTime= + "5184000", commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 5,184,000 seconds (60 days) from the current epoch time. | N | +| 9 | Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time | tokenId=, expirationTime= + "2592000", commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 2,592,000 seconds (30 days) from the current epoch time. | N | +| 10 | Updates a mutable token to an expiration time of 30 days minus one second (2,591,999 seconds) from the current time | tokenId=, expirationTime= + "2591999", commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | +| 11 | Updates a mutable token with an expiration time 8,000,001 seconds from the current time | tokenId=, expirationTime= + "8000001", commonTransactionParams.signers=[] | The token update succeeds and the token has an expiration time 8,000,001 from the current epoch time. | N | +| 12 | Updates a mutable token with an expiration time 8,000,002 seconds from the current time | tokenId=, expirationTime= + "8000002", commonTransactionParams.signers=[] | The token update fails with an INVALID_EXPIRATION_TIME response code from the network. | N | #### JSON Request Example @@ -576,7 +572,7 @@ The tests contained in this specification will assume that two valid token were "method": "updateToken", "params": { "tokenId": "0.0.3315", - "expirationTime": 5184000 + "expirationTime": "5184000" } } ``` diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index b8e7da9..25fd18f 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -17,11 +17,6 @@ import { } from "../../utils/helpers/key.js"; import { getRawKeyFromHex } from "../../utils/helpers/asn1-decoder.js"; -// Needed to convert BigInts to JSON number format. -BigInt.prototype.toJSON = function () { - return JSON.rawJSON(this.toString()); -}; - /** * Tests for TokenCreateTransaction */ diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js index e9d4df1..9d2e38f 100644 --- a/test/token-service/test_tokenUpdateTransaction.js +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -13,15 +13,10 @@ import { getPublicKeyFromMirrorNode, } from "../../utils/helpers/key.js"; -// Needed to convert BigInts to JSON number format. -BigInt.prototype.toJSON = function () { - return JSON.rawJSON(this.toString()); -}; - /** * Tests for TokenUpdateTransaction */ -describe.only("TokenUpdateTransaction", function () { +describe("TokenUpdateTransaction", function () { // Tests should not take longer than 30 seconds to fully execute. this.timeout(30000); @@ -2802,43 +2797,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { - try { - const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, - autoRenewPeriod: "18446744073709551615", - commonTransactionParams: { - signers: [mutableTokenKey], - }, - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#7) Updates a mutable token with an auto renew period set to 18,446,744,073,709,551,614 (uint64 max - 1) seconds", async function () { - try { - const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, - autoRenewPeriod: "18446744073709551614", - commonTransactionParams: { - signers: [mutableTokenKey], - }, - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); - return; - } - - assert.fail("Should throw an error"); - }); - - it.skip("(#8) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + it.skip("(#6) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,808 (int64 min) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2856,7 +2815,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#9) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { + it("(#7) Updates a mutable token with an auto renew period set to -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2874,7 +2833,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Updates a mutable token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { + it("(#8) Updates a mutable token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { const autoRenewPeriod = "5184000"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2889,7 +2848,7 @@ describe.only("TokenUpdateTransaction", function () { }); }); - it("(#11) Updates a mutable token with an auto renew period set to 30 days (2,592,000 seconds)", async function () { + it("(#9) Updates a mutable token with an auto renew period set to 30 days (2,592,000 seconds)", async function () { const autoRenewPeriod = "2592000"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2904,7 +2863,7 @@ describe.only("TokenUpdateTransaction", function () { }); }); - it("(#12) Updates a mutable token with an auto renew period set to 30 days minus one second (2,591,999 seconds)", async function () { + it("(#10) Updates a mutable token with an auto renew period set to 30 days minus one second (2,591,999 seconds)", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2922,7 +2881,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#13) Updates a mutable token with an auto renew period set to 8,000,001 seconds", async function () { + it("(#11) Updates a mutable token with an auto renew period set to 8,000,001 seconds", async function () { const autoRenewPeriod = "8000001"; const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -2937,7 +2896,7 @@ describe.only("TokenUpdateTransaction", function () { }); }); - it("(#14) Updates a mutable token with an auto renew period set to 8,000,002 seconds", async function () { + it("(#12) Updates a mutable token with an auto renew period set to 8,000,002 seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3067,43 +3026,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Updates a mutable token to an expiration time of 18,446,744,073,709,551,615 (uint64 max) seconds", async function () { - try { - const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, - expirationTime: "18446744073709551615", - commonTransactionParams: { - signers: [mutableTokenKey], - }, - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#7) Updates a mutable token to an expiration time of 18,446,744,073,709,551,614 (uint64 max - 1) seconds", async function () { - try { - const response = await JSONRPCRequest("updateToken", { - tokenId: mutableTokenId, - expirationTime: "18446744073709551614", - commonTransactionParams: { - signers: [mutableTokenKey], - }, - }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { - assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); - return; - } - - assert.fail("Should throw an error"); - }); - - it("(#8) Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + it("(#6) Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3121,7 +3044,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#9) Updates a mutable token to an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { + it("(#7) Updates a mutable token to an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3139,7 +3062,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - //it("(#10) Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { + //it("(#8) Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { // const expirationTime = parseInt((Date.now() / 1000) + 5184000); // const response = await JSONRPCRequest("updateToken", { // tokenId: mutableTokenId, @@ -3155,7 +3078,7 @@ describe.only("TokenUpdateTransaction", function () { // verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); //}); - //it("(#11) Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { + //it("(#9) Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { // const expirationTime = parseInt((Date.now() / 1000) + 2592000); // const response = await JSONRPCRequest("updateToken", { // tokenId: mutableTokenId, @@ -3171,7 +3094,7 @@ describe.only("TokenUpdateTransaction", function () { // verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); //}); - it("(#12) Updates a mutable to an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { + it("(#10) Updates a mutable to an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId, @@ -3189,7 +3112,7 @@ describe.only("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#13) Updates a mutable token to an expiration time 8,000,001 seconds from the current time", async function () { + it("(#11) Updates a mutable token to an expiration time 8,000,001 seconds from the current time", async function () { const expirationTime = ( Math.floor(Date.now() / 1000) + 8000001 ).toString(); @@ -3208,7 +3131,7 @@ describe.only("TokenUpdateTransaction", function () { }); }); - it("(#14) Updates a mutable token to an expiration time 8,000,002 seconds from the current time", async function () { + it("(#12) Updates a mutable token to an expiration time 8,000,002 seconds from the current time", async function () { try { const response = await JSONRPCRequest("updateToken", { tokenId: mutableTokenId,