From 1e83f438699b2bc81bfa391076dc9aedea87b8e6 Mon Sep 17 00:00:00 2001 From: Rob Walworth <110835868+rwalworth@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:39:34 -0500 Subject: [PATCH 01/12] docs: Add test specifications for `TokenAssociateTransaction` (#264) Signed-off-by: Rob Walworth --- .../tokenAssociateTransaction.md | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 test-specifications/token-service/tokenAssociateTransaction.md diff --git a/test-specifications/token-service/tokenAssociateTransaction.md b/test-specifications/token-service/tokenAssociateTransaction.md new file mode 100644 index 0000000..6cafad0 --- /dev/null +++ b/test-specifications/token-service/tokenAssociateTransaction.md @@ -0,0 +1,145 @@ +# TokenAssociateTransaction - Test specification + +## Description: +This test specification for TokenAssociateTransaction is to be one of many for testing the functionality of the Hedera SDKs. The SDK under test will use the language specific JSON-RPC server return responses back to the test driver. + +## Design: +Each test within the test specification is linked to one of the properties within TokenAssociateTransaction. Each property is tested with a mix of boundaries. The inputs for each test are a range of valid, minimum, maximum, negative and invalid values for the method. The expected response of a passed test can be a correct error response code or seen as the result of node queries. A successful transaction (the transaction reached consensus and was applied to state) can be determined by getting a `TransactionReceipt` or `TransactionRecord`, or can be determined by using queries such as `TokenInfoQuery` or `TokenBalanceQuery` and investigating for the required changes (creations, updates, etc.). The mirror node can also be used to determine if a transaction was successful via its rest API. Error codes are obtained from the response code proto files. + +**Transaction properties:** + +https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account + +**TokenAssociate protobufs:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/token_associate.proto + +**Response codes:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto + +**Mirror Node APIs:** + +https://docs.hedera.com/hedera/sdks-and-apis/rest-api + +## JSON-RPC API Endpoint Documentation + +### Method Name + +`associateToken` + +### Input Parameters + +| Parameter Name | Type | Required/Optional | Description/Notes | +|-------------------------|--------------------------------------------------|-------------------|--------------------------------------------------------| +| accountId | string | optional | The ID of the account with which to associate a token. | +| tokenIds | list | optional | The IDs of the tokens to associate. | +| commonTransactionParams | [json object](../commonTransactionParameters.md) | optional | | + +### Output Parameters + +| Parameter Name | Type | Description/Notes | +|----------------|--------|----------------------------------------------------------------------------------------| +| status | string | The status of the submitted `TokenAssociateTransaction` (from a `TransactionReceipt`). | + +### Additional Notes + +The tests contained in this specification will assume that a valid account and a valid token were already successfully created. will denote the ID of the account, and will denote the private key of the account as a DER-encoded hex string. The token shall be created with default values name="testname", symbol="testsymbol", treasuryAccountId=, and tokenType="ft". will denote the ID of the created token. The account will only need to be created once, but a new token should be created for each test. + +## Property Tests + +### **Account ID:** + +- The ID of the account with which to associate a token. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|-----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|-------------------| +| 1 | Associates a token with an account | accountId=, tokenIds=[], commonTransactionParams.signers=[] | The token association succeeds and the token is associated with . | N | +| 2 | Associates a token with an account with which it is already associated | accountId=, tokenIds=[], commonTransactionParams.signers=[] | The token association fails with an TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT response code from the network. | N | +| 3 | Associates a token with an account without signing with the account's private key | accountId=, tokenIds=[] | The token association fails with an INVALID_SIGNATURE response code from the network. | N | +| 4 | Associates a token with an account that doesn't exist | accountId="123.456.789", tokenIds=[] | The token association fails with an INVALID_ACCOUNT_ID response code from the network. | N | +| 5 | Associates a token with an account that is deleted | accountId=, tokenIds=[], commonTransactionParams.signers=[] | The token association fails with an INVALID_ACCOUNT_ID response code from the network. | N | +| 6 | Associates a token with an empty account | accountId="", tokenIds=[] | The token association fails with an SDK internal error. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "method": "associateToken", + "params": { + "accountId": "0.0.2533", + "tokenIds": [ + "0.0.579680", + "0.0.90649" + ], + "commonTransactionParams": { + "signers": [ + "302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "result": { + "status": "SUCCESS" + } +} +``` + +### **Token IDs:** + +- The IDs of the tokens to associate. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------|-------------------| +| 1 | Associates no tokens with an account | accountId=, commonTransactionParams.signers=[] | The token association succeeds and no associations are made. | N | +| 2 | Associates a token that doesn't exist with an account | accountId=, tokenIds=["123.456.789"], commonTransactionParams.signers=[] | The token association fails with an INVALID_TOKEN_ID response code from the network. | N | +| 3 | Associates a token that is deleted with an account | accountId=, tokenIds=[], commonTransactionParams.signers=[] | The token association fails with an TOKEN_WAS_DELETED response code from the network. | N | +| 4 | Associates a token that is empty with an account | accountId=, tokenIds=[""], commonTransactionParams.signers=[] | The token association fails with an SDK internal error. | N | +| 5 | Associates a token twice with an account | accountId=, tokenIds=[, ], commonTransactionParams.signers=[] | The token association fails with an TOKEN_ID_REPEATED_IN_TOKEN_LIST response code from the network. | N | +| 6 | Associates three valid tokens with an account | accountId=, tokenIds=[, , ], commonTransactionParams.signers=[] | The token association succeeds and the tokens are associated with . | N | +| 7 | Associates two valid tokens and an invalid token with an account | accountId=, tokenIds=[, , "123.456.789"], commonTransactionParams.signers=[] | The token association fails with an INVALID_TOKEN_ID response code from the network. | N | +| 8 | Associates two valid tokens and a deleted token with an account | accountId=, tokenIds=[, , ], commonTransactionParams.signers=[] | The token association fails with an TOKEN_WAS_DELETED response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "method": "associateToken", + "params": { + "accountId": "0.0.2533", + "tokenIds": [ + "0.0.579680", + "0.0.90649" + ], + "commonTransactionParams": { + "signers": [ + "302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "result": { + "status": "SUCCESS" + } +} +``` From f4bb28b5ac1f9454866a0fc6f38fe24dd45480d6 Mon Sep 17 00:00:00 2001 From: ivaylogarnev Date: Wed, 20 Nov 2024 09:20:26 +0200 Subject: [PATCH 02/12] feat(tokenDeleteTransaction): Implement TokenDeleteTransaction E2E tests: TCK (#256) Signed-off-by: ivaylogarnev-limechain --- .../test_tokenCreateTransaction.js | 1 + .../test_tokenDeleteTransaction.js | 188 ++++++++++++++++++ utils/helpers/token.js | 44 ++++ 3 files changed, 233 insertions(+) create mode 100644 test/token-service/test_tokenDeleteTransaction.js create mode 100644 utils/helpers/token.js diff --git a/test/token-service/test_tokenCreateTransaction.js b/test/token-service/test_tokenCreateTransaction.js index 6535cb9..8a0bfb1 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -4726,6 +4726,7 @@ describe("TokenCreateTransaction", function () { let response = await JSONRPCRequest(this, "createToken", { name: "testname", symbol: "testsymbol", + adminKey: process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); diff --git a/test/token-service/test_tokenDeleteTransaction.js b/test/token-service/test_tokenDeleteTransaction.js new file mode 100644 index 0000000..e08ac96 --- /dev/null +++ b/test/token-service/test_tokenDeleteTransaction.js @@ -0,0 +1,188 @@ +import { assert } from "chai"; + +import { JSONRPCRequest } from "../../client.js"; +import { setOperator } from "../../setup_Tests.js"; + +import { + verifyTokenIsDeleted, + getNewFungibleTokenId, +} from "../../utils/helpers/token.js"; +import { retryOnError } from "../../utils/helpers/retry-on-error.js"; +/** + * Tests for TokenDeleteTransaction + */ +describe("TokenDeleteTransaction", 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(this, "reset"); + }); + + describe("Token ID", function () { + it("(#1) Deletes an immutable token", async function () { + const response = await JSONRPCRequest(this, "createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + }); + + const tokenId = response.tokenId; + + try { + await JSONRPCRequest(this, "deleteToken", { + tokenId, + commonTransactionParams: { + signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], + }, + }); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#2) Deletes a mutable token", async function () { + const tokenId = await getNewFungibleTokenId(this); + + await JSONRPCRequest(this, "deleteToken", { + tokenId, + commonTransactionParams: { + signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], + }, + }); + + await retryOnError(async () => { + verifyTokenIsDeleted(tokenId); + }); + }); + + it("(#3) Deletes a token that doesn't exist", async function () { + try { + await JSONRPCRequest(this, "deleteToken", { + tokenId: "123.456.789", + commonTransactionParams: { + signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_TOKEN_ID"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#4) Deletes a token with no token ID", async function () { + try { + await JSONRPCRequest(this, "deleteToken", { + tokenId: "", + commonTransactionParams: { + signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], + }, + }); + } catch (err) { + assert.equal(err.message, "Internal error"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#5) Deletes a token that was already deleted", async function () { + try { + const tokenId = await getNewFungibleTokenId(this); + + await JSONRPCRequest(this, "deleteToken", { + tokenId: tokenId, + commonTransactionParams: { + signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], + }, + }); + + // Trying to delete a token once again + await JSONRPCRequest(this, "deleteToken", { + tokenId: tokenId, + commonTransactionParams: { + signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], + }, + }); + } catch (err) { + assert.equal(err.data.status, "TOKEN_WAS_DELETED"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#6) Deletes a token without signing with the token's admin key", async function () { + try { + // Passing other admin key in order to throw an error + const privateKey = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const tokenId = await getNewFungibleTokenId(this, privateKey.key); + + await JSONRPCRequest(this, "deleteToken", { + tokenId: tokenId, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + + it("(#7) Deletes a token but signs with an incorrect private key", async function () { + try { + const privateKey = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + // Creating an account to use its accountId for creating the token + // and after that signing it with different private key + const createdAccount = await JSONRPCRequest(this, "createAccount", { + key: privateKey.key, + }); + + const tokenId = await getNewFungibleTokenId( + this, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + createdAccount.accountId, + ); + + // Trying to delete a token once again + await JSONRPCRequest(this, "deleteToken", { + tokenId: tokenId, + commonTransactionParams: { + signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + // The test failed, no error was thrown. + assert.fail("Should throw an error"); + }); + }); + + return Promise.resolve(); +}); diff --git a/utils/helpers/token.js b/utils/helpers/token.js new file mode 100644 index 0000000..13e487e --- /dev/null +++ b/utils/helpers/token.js @@ -0,0 +1,44 @@ +import { expect } from "chai"; + +import consensusInfoClient from "../../consensusInfoClient.js"; +import mirrorNodeClient from "../../mirrorNodeClient.js"; +import { JSONRPCRequest } from "../../client.js"; + +/** + * Verifies that a token has been deleted by checking both the Consensus Info + * and the Mirror Node API. + * + * @async + * @param {string} tokenId - The ID of the token to verify. + * @throws {Error} Will throw an error if the token is not marked as deleted in either Consensus Info or Mirror Node. + */ +export const verifyTokenIsDeleted = async (tokenId) => { + expect(await (await consensusInfoClient.getTokenInfo(tokenId)).isDeleted).to + .be.true; + + expect(await (await mirrorNodeClient.getTokenData(tokenId)).deleted).to.be + .true; +}; + +/** + * Creates a new fungible token via a JSON-RPC request and returns its token ID. + * @async + * @param {string} mochaTestContext - The context of the Mocha test. If provided, the test will be skipped if the method is not implemented. + * @param {string} [adminKey] - The private key of the admin (optional). Defaults to `process.env.OPERATOR_ACCOUNT_PRIVATE_KEY` if not provided. + * @param {string} [treasuryAccountId] - The account ID of the treasury (optional). Defaults to `process.env.OPERATOR_ACCOUNT_ID` if not provided. + * @returns {Promise} - The ID of the newly created fungible token. + */ +export const getNewFungibleTokenId = async ( + mochaTestContext, + adminKey, + treasuryAccountId, +) => { + const tokenResponse = await JSONRPCRequest(mochaTestContext, "createToken", { + name: "testname", + symbol: "testsymbol", + adminKey: adminKey || process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + treasuryAccountId: treasuryAccountId || process.env.OPERATOR_ACCOUNT_ID, + }); + + return tokenResponse.tokenId; +}; From d6c46fed4693f2f469b331e2c00645414d8312da Mon Sep 17 00:00:00 2001 From: ivaylogarnev Date: Wed, 20 Nov 2024 09:23:43 +0200 Subject: [PATCH 03/12] feat(tokenUpdateTransaction): Implement `TokenUpdateTransaction` E2E tests: TCK (#263) Signed-off-by: Rob Walworth Signed-off-by: ivaylogarnev-limechain Co-authored-by: Rob Walworth --- .../token-service/tokenUpdateTransaction.md | 62 +- .../test_tokenCreateTransaction.js | 98 +- .../test_tokenUpdateTransaction.js | 3397 +++++++++++++++++ utils/helpers/key.js | 4 + ...verify-token-key.js => verify-token-tx.js} | 47 +- 5 files changed, 3509 insertions(+), 99 deletions(-) create mode 100644 test/token-service/test_tokenUpdateTransaction.js rename utils/helpers/{verify-token-key.js => verify-token-tx.js} (56%) diff --git a/test-specifications/token-service/tokenUpdateTransaction.md b/test-specifications/token-service/tokenUpdateTransaction.md index 2178e8c..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,21 +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 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 | +| 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 @@ -530,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" } } ``` @@ -553,21 +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 | -| 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 | +| 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 @@ -578,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 8a0bfb1..cb554f1 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/test/token-service/test_tokenCreateTransaction.js @@ -1,6 +1,5 @@ import crypto from "crypto"; import { assert, expect } from "chai"; -import { Timestamp } from "@hashgraph/sdk"; import { JSONRPCRequest } from "../../client.js"; import mirrorNodeClient from "../../mirrorNodeClient.js"; @@ -15,7 +14,8 @@ import { import { verifyTokenKey, verifyTokenKeyList, -} from "../../utils/helpers/verify-token-key.js"; + verifyTokenExpirationTimeUpdate, +} from "../../utils/helpers/verify-token-tx.js"; import { verifyTokenCreationWithFixedFee, verifyTokenCreationWithFractionalFee, @@ -478,7 +478,7 @@ describe("TokenCreateTransaction", function () { ); }); - it.skip("(#5) Creates a fungible token with -9,223,372,036,854,775,808 (int64 min) initial supply", async function () { + it("(#5) Creates a fungible token with -9,223,372,036,854,775,808 (int64 min) initial supply", async function () { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1707,32 +1707,6 @@ describe("TokenCreateTransaction", function () { }); describe("Expiration Time", function () { - async function verifyTokenCreationWithExpirationTime( - tokenId, - expirationTime, - ) { - 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) Creates a token with an expiration time of 0 seconds", async function () { try { await JSONRPCRequest(this, "createToken", { @@ -1797,7 +1771,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#5) Creates a token with an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + it("(#5) Creates a token with an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1850,31 +1824,32 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: expirationTime, + expirationTime, }); - await verifyTokenCreationWithExpirationTime( - response.tokenId, - expirationTime, - ); + await verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); }); - //it("(#9) 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(this,"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.skip("(#9) Creates a token with an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { + const expirationTime = ( + Math.floor(Date.now() / 1000) + 2591999 + ).toString(); + + try { + const response = await JSONRPCRequest(this, "createToken", { + name: "testname", + symbol: "testsymbol", + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + expirationTime, + }); + 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 8,000,001 seconds from the current time", async function () { const expirationTime = ( @@ -1885,13 +1860,10 @@ describe("TokenCreateTransaction", function () { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, - expirationTime: expirationTime, + expirationTime, }); - await verifyTokenCreationWithExpirationTime( - response.tokenId, - expirationTime, - ); + await verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); }); it("(#11) Creates a token with an expiration time of 8,000,002 seconds from the current time", async function () { @@ -2488,7 +2460,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); }); - it.skip("(#5) Creates a token with -9,223,372,036,854,775,808 (int64 min) max supply", async function () { + it("(#5) Creates a token with -9,223,372,036,854,775,808 (int64 min) max supply", async function () { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2505,7 +2477,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#6) Creates a token with -9,223,372,036,854,775,807 (int64 min) max supply", async function () { + it("(#6) Creates a token with -9,223,372,036,854,775,807 (int64 min) max supply", async function () { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2818,7 +2790,7 @@ describe("TokenCreateTransaction", function () { ); }); - it.skip("(#5) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + it("(#5) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,808 (int64 min)", async function () { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3000,7 +2972,7 @@ describe("TokenCreateTransaction", function () { ); }); - it.skip("(#11) Creates a token with a fractional fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async function () { + it("(#11) Creates a token with a fractional fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async function () { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3190,7 +3162,7 @@ describe("TokenCreateTransaction", function () { ); }); - it.skip("(#17) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async function () { + it("(#17) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async function () { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3375,7 +3347,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#23) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + it("(#23) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3576,7 +3548,7 @@ describe("TokenCreateTransaction", function () { ); }); - it.skip("(#29) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + it("(#29) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { try { await JSONRPCRequest(this, "createToken", { name: "testname", diff --git a/test/token-service/test_tokenUpdateTransaction.js b/test/token-service/test_tokenUpdateTransaction.js new file mode 100644 index 0000000..3f25579 --- /dev/null +++ b/test/token-service/test_tokenUpdateTransaction.js @@ -0,0 +1,3397 @@ +import crypto from "crypto"; +import { assert, expect } from "chai"; + +import { JSONRPCRequest } from "../../client.js"; +import mirrorNodeClient from "../../mirrorNodeClient.js"; +import consensusInfoClient from "../../consensusInfoClient.js"; +import { setOperator } from "../../setup_Tests.js"; + +import { retryOnError } from "../../utils/helpers/retry-on-error.js"; +import { + verifyTokenKey, + verifyTokenKeyList, + verifyTokenUpdateWithNullKey, + verifyTokenExpirationTimeUpdate, +} from "../../utils/helpers/verify-token-tx.js"; + +import { + fourKeysKeyListParams, + twoLevelsNestedKeyListParams, + twoThresholdKeyParams, +} from "../../utils/helpers/constants/key-list.js"; + +/** + * Tests for TokenUpdateTransaction + */ +describe("TokenUpdateTransaction", 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, mutableTokenKey; + + beforeEach(async function () { + await setOperator( + process.env.OPERATOR_ACCOUNT_ID, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + ); + + // Generate an immutable token. + const response = await JSONRPCRequest(this, "createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + initialSupply: initialSupply, + tokenType: "ft", + }); + + immutableTokenId = response.tokenId; + + await JSONRPCRequest(this, "reset"); + }); + + beforeEach(async function () { + await setOperator( + process.env.OPERATOR_ACCOUNT_ID, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + ); + + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + mutableTokenKey = response.key; + + response = await JSONRPCRequest(this, "createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + kycKey: mutableTokenKey, + freezeKey: mutableTokenKey, + wipeKey: mutableTokenKey, + supplyKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + feeScheduleKey: mutableTokenKey, + pauseKey: mutableTokenKey, + metadataKey: mutableTokenKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + mutableTokenId = response.tokenId; + }); + + afterEach(async function () { + await JSONRPCRequest(this, "reset"); + }); + + describe("Token ID", function () { + async function verifyTokenUpdate(tokenId) { + 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 () { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + }); + + await retryOnError(async () => verifyTokenUpdate(immutableTokenId)); + }); + + it("(#2) Updates a mutable token with no updates", async function () { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + }); + + await retryOnError(async () => verifyTokenUpdate(mutableTokenId)); + }); + + it("(#3) Updates a token with no token ID", async function () { + try { + await JSONRPCRequest(this, "updateToken", {}); + } 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 ( + 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 { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + symbol: "t", + }); + } 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"; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + symbol: symbol, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => + verifyTokenSymbolUpdate(mutableTokenId, symbol), + ); + }); + + it("(#3) Updates a mutable token with a symbol that is empty", async function () { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + symbol: "", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => + // Symbol shouldn't change and should still remain as its initial value. + verifyTokenSymbolUpdate(mutableTokenId, 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"; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + symbol: symbol, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => + verifyTokenSymbolUpdate(mutableTokenId, symbol), + ); + }); + + it("(#5) Updates a mutable token with a symbol that exceeds the maximum length", async function () { + try { + await JSONRPCRequest(this, "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: [mutableTokenKey], + }, + }); + } 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 { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + symbol: "t", + }); + } 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 ( + 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 { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + name: "t", + }); + } 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 name that is the minimum length", async function () { + const name = "t"; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + name: name, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => + verifyTokenNameUpdate(mutableTokenId, name), + ); + }); + + it("(#3) Updates a mutable token with a name that is empty", async function () { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + name: "", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Name shouldn't change and should still remain as its initial value. + await retryOnError(async () => + verifyTokenNameUpdate(mutableTokenId, 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!!"; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + name: name, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => + verifyTokenNameUpdate(mutableTokenId, name), + ); + }); + + it("(#5) Updates a mutable token with a name that exceeds the maximum length", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + 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], + }, + }); + } catch (err) { + 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 name without signing with the token's admin key", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + name: "t", + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Treasury Account ID", function () { + it("(#1) Updates an immutable token with a treasury account", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, + }); + } 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 treasury account", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const key = response.key; + + // Create with 1 auto token association in order to automatically associate with the created token. + response = await JSONRPCRequest(this, "createAccount", { + key: key, + maxAutoTokenAssociations: 1, + }); + + const accountId = response.accountId; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + treasuryAccountId: accountId, + commonTransactionParams: { + signers: [mutableTokenKey, key], + }, + }); + + 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._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()); + }); + + it("(#3) Updates a mutable token with a treasury account without signing with the account's private key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createAccount", { + key, + }); + + const accountId = response.accountId; + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + treasuryAccountId: accountId, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#4) Updates a mutable token with a treasury account that doesn't exist", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + treasuryAccountId: "123.456.789", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_ACCOUNT_ID"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#5) Updates a mutable token with a treasury account that is deleted", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createAccount", { + key: key, + }); + + const accountId = response.accountId; + + response = await JSONRPCRequest(this, "deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [key], + }, + }); + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + treasuryAccountId: accountId, + commonTransactionParams: { + signers: [mutableTokenKey, key], + }, + }); + } 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(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createAccount", { + key, + }); + + const accountId = response.accountId; + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + treasuryAccountId: accountId, + commonTransactionParams: { + signers: [key], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Admin Key", function () { + it("(#1) Updates an immutable token with a valid key as its admin key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + }); + + const key = response.key; + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + adminKey: key, + }); + } 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(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + adminKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey, privateKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "adminKey"), + ); + }); + + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its admin key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + adminKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey, privateKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "adminKey"), + ); + }); + + it("(#4) Updates a mutable token with a valid ED25519 private key as its admin key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + adminKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey, privateKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "adminKey"), + ); + }); + + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its admin key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + adminKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey, privateKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "adminKey"), + ); + }); + + 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( + this, + "generateKey", + fourKeysKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + adminKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, keyList.key, "adminKey"), + ); + }); + + 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( + this, + "generateKey", + twoLevelsNestedKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + adminKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, nestedKeyList.key, "adminKey"), + ); + }); + + 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( + this, + "generateKey", + twoThresholdKeyParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + adminKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, thresholdKey.key, "adminKey"), + ); + }); + + 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(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + }); + + const key = response.key; + + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + adminKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#10) Updates a mutable token with an invalid key as its admin key", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + adminKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("KYC Key", function () { + it("(#1) Updates an immutable token with a valid key as its KYC key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + }); + + const key = response.key; + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + kycKey: key, + }); + } 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(this, "generateKey", { + type: "ed25519PublicKey", + }); + + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + kycKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "kycKey"), + ); + }); + + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its KYC key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + }); + + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + kycKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "kycKey"), + ); + }); + + it("(#4) Updates a mutable token with a valid ED25519 private key as its KYC key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + kycKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey, privateKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "kycKey"), + ); + }); + + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its KYC key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + kycKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "kycKey"), + ); + }); + + 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( + this, + "generateKey", + fourKeysKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + kycKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, keyList.key, "kycKey"), + ); + }); + + 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( + this, + "generateKey", + twoLevelsNestedKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + kycKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, nestedKeyList.key, "kycKey"), + ); + }); + + 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( + this, + "generateKey", + twoThresholdKeyParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + kycKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, thresholdKey.key, "kycKey"), + ); + }); + + it("(#9) Updates a mutable token with an empty KeyList as its KYC key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "keyList", + keys: [], + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + kycKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => + verifyTokenUpdateWithNullKey(mutableTokenId, "kycKey"), + ); + }); + + 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(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + const tokenId = response.tokenId; + + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: tokenId, + kycKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_KYC_KEY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#11) Updates a mutable token with an invalid key as its KYC key", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + kycKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Freeze Key", function () { + it("(#1) Updates an immutable token with a valid key as its freeze key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + }); + + const key = response.key; + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + freezeKey: key, + }); + } 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(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + freezeKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "freezeKey"), + ); + }); + + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its freeze key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + freezeKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "freezeKey"), + ); + }); + + it("(#4) Updates a mutable token with a valid ED25519 private key as its freeze key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + freezeKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "freezeKey"), + ); + }); + + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its freeze key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + freezeKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "freezeKey"), + ); + }); + + 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( + this, + "generateKey", + fourKeysKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + freezeKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, keyList.key, "freezeKey"), + ); + }); + + 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( + this, + "generateKey", + twoLevelsNestedKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + freezeKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, nestedKeyList.key, "freezeKey"), + ); + }); + + 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( + this, + "generateKey", + twoThresholdKeyParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + freezeKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, thresholdKey.key, "freezeKey"), + ); + }); + + it("(#9) Updates a mutable token with an empty KeyList as its freeze key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "keyList", + keys: [], + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + freezeKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => + verifyTokenUpdateWithNullKey(mutableTokenId, "freezeKey"), + ); + }); + + 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(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + const tokenId = response.tokenId; + + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: tokenId, + freezeKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_FREEZE_KEY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#11) Updates a mutable token with an invalid key as its freeze key", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + freezeKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Wipe Key", function () { + it("(#1) Updates an immutable token with a valid key as its wipe key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + }); + + const key = response.key; + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + wipeKey: key, + }); + } 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(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + wipeKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "wipeKey"), + ); + }); + + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its wipe key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + wipeKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "wipeKey"), + ); + }); + + it("(#4) Updates a mutable token with a valid ED25519 private key as its wipe key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + wipeKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "wipeKey"), + ); + }); + + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its wipe key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + wipeKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "wipeKey"), + ); + }); + + 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( + this, + "generateKey", + fourKeysKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + wipeKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, keyList.key, "wipeKey"), + ); + }); + + 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( + this, + "generateKey", + twoLevelsNestedKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + wipeKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, nestedKeyList.key, "wipeKey"), + ); + }); + + 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( + this, + "generateKey", + twoThresholdKeyParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + wipeKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, thresholdKey.key, "wipeKey"), + ); + }); + + it("(#9) Updates a mutable token with an empty KeyList as its wipe key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "keyList", + keys: [], + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + wipeKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => + verifyTokenUpdateWithNullKey(mutableTokenId, "wipeKey"), + ); + }); + + 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(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + const tokenId = response.tokenId; + + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: tokenId, + wipeKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_WIPE_KEY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#11) Updates a mutable token with an invalid key as its wipe key", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + wipeKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Supply Key", function () { + it("(#1) Updates an immutable token with a valid key as its supply key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + }); + + const key = response.key; + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + supplyKey: key, + }); + } 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(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + supplyKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "supplyKey"), + ); + }); + + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its supply key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + supplyKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "supplyKey"), + ); + }); + + it("(#4) Updates a mutable token with a valid ED25519 private key as its supply key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + supplyKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "supplyKey"), + ); + }); + + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its supply key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + supplyKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => + verifyTokenKey(mutableTokenId, publicKey, "supplyKey"), + ); + }); + + 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( + this, + "generateKey", + fourKeysKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + supplyKey: keyList.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + keyList.privateKeys[0], + keyList.privateKeys[1], + keyList.privateKeys[2], + keyList.privateKeys[3], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, keyList.key, "supplyKey"), + ); + }); + + 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( + this, + "generateKey", + twoLevelsNestedKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + supplyKey: nestedKeyList.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + nestedKeyList.privateKeys[0], + nestedKeyList.privateKeys[1], + nestedKeyList.privateKeys[2], + nestedKeyList.privateKeys[3], + nestedKeyList.privateKeys[4], + nestedKeyList.privateKeys[5], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, nestedKeyList.key, "supplyKey"), + ); + }); + + 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( + this, + "generateKey", + twoThresholdKeyParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + supplyKey: thresholdKey.key, + commonTransactionParams: { + signers: [ + mutableTokenKey, + thresholdKey.privateKeys[0], + thresholdKey.privateKeys[1], + ], + }, + }); + + await retryOnError(async () => + verifyTokenKeyList(mutableTokenId, thresholdKey.key, "supplyKey"), + ); + }); + + it("(#9) Updates a mutable token with an empty KeyList as its supply key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "keyList", + keys: [], + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + supplyKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenUpdateWithNullKey(mutableTokenId, "supplyKey"); + }); + }); + + 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(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + const tokenId = response.tokenId; + + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: tokenId, + supplyKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#11) Updates a mutable token with an invalid key as its supply key", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + supplyKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Auto Renew Account", function () { + it("(#1) Updates an immutable token with an auto renew account", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + autoRenewAccountId: process.env.OPERATOR_ACCOUNT_ID, + }); + } 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(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createAccount", { + key: key, + }); + + const accountId = response.accountId; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [mutableTokenKey, key], + }, + }); + + 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 () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createAccount", { + key: key, + }); + + const accountId = response.accountId; + + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_SIGNATURE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#4) Updates a mutable token with an auto renew account that doesn't exist", async function () { + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewAccountId: "123.456.789", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#5) Updates a mutable token with an empty auto renew account", async function () { + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewAccountId: "", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + 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(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createAccount", { + key: key, + }); + + const accountId = response.accountId; + + response = await JSONRPCRequest(this, "deleteAccount", { + deleteAccountId: accountId, + transferAccountId: process.env.OPERATOR_ACCOUNT_ID, + commonTransactionParams: { + signers: [key], + }, + }); + + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [mutableTokenKey, key], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); + return; + } + + assert.fail("Should throw an error"); + }); + + 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(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createAccount", { + key: key, + }); + + const accountId = response.accountId; + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewAccountId: accountId, + commonTransactionParams: { + signers: [key], + }, + }); + } 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 ( + await consensusInfoClient.getTokenInfo(tokenId) + ).autoRenewPeriod, + ); + + expect(autoRenewPeriod).to.equal( + 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 () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + autoRenewPeriod: "5184000", + }); + } 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 period set to 0 seconds", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: "0", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#3) Updates a mutable token with an auto renew period set to -1 seconds", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: "-1", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); + return; + } + + assert.fail("Should throw an error"); + }); + + 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 { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: "9223372036854775807", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); + return; + } + + assert.fail("Should throw an error"); + }); + + 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 { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: "9223372036854775806", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); + return; + } + + assert.fail("Should throw an error"); + }); + + 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 { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: "-9223372036854775808", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } 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 -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: "-9223372036854775807", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#8) Updates a mutable token with an auto renew period set to 60 days (5,184,000 seconds)", async function () { + const autoRenewPeriod = "5184000"; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: autoRenewPeriod, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenAutoRenewPeriodUpdate(mutableTokenId, autoRenewPeriod); + }); + }); + + it("(#9) Updates a mutable token with an auto renew period set to 30 days (2,592,000 seconds)", async function () { + const autoRenewPeriod = "2592000"; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: autoRenewPeriod, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenAutoRenewPeriodUpdate(mutableTokenId, autoRenewPeriod); + }); + }); + + 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 { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: "2591999", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } 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 8,000,001 seconds", async function () { + const autoRenewPeriod = "8000001"; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: autoRenewPeriod, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenAutoRenewPeriodUpdate(mutableTokenId, autoRenewPeriod); + }); + }); + + it("(#12) Updates a mutable token with an auto renew period set to 8,000,002 seconds", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + autoRenewPeriod: "8000002", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Expiration Time", function () { + it.skip("(#1) Updates an immutable token with a valid expiration time", async function () { + const expirationTime = ( + Math.floor(Date.now() / 1000) + 5184000 + ).toString(); + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + expirationTime, + }); + } 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 { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + expirationTime: "0", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#3) Updates a mutable token to an expiration time of -1", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + expirationTime: "-1", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#4) Updates a mutable token to an expiration time of 9,223,372,036,854,775,807 (int64 max) seconds", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + expirationTime: "9223372036854775807", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + 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 { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + expirationTime: "9223372036854775806", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it.skip("(#6) Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + expirationTime: "-9223372036854775808", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } 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 -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + expirationTime: "-9223372036854775807", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + it.skip("(#8) Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { + const expirationTime = ( + Math.floor(Date.now() / 1000) + 5184000 + ).toString(); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + expirationTime, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + }); + + it.skip("(#9) Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { + const expirationTime = ( + Math.floor(Date.now() / 1000) + 2592000 + ).toString(); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + expirationTime, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + }); + + 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 { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + expirationTime: "2591999", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + + 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(); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + expirationTime: expirationTime, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenExpirationTimeUpdate(mutableTokenId, expirationTime); + }); + }); + + it("(#12) Updates a mutable token to an expiration time 8,000,002 seconds from the current time", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + expirationTime: "8000002", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Memo", function () { + async function verifyTokenMemoUpdate(tokenId, 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 () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + memo: "testmemo", + }); + } 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"; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + memo: memo, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenMemoUpdate(mutableTokenId, memo); + }); + }); + + it("(#3) Updates a mutable token with a memo that is the minimum length", async function () { + const memo = ""; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + memo: memo, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenMemoUpdate(mutableTokenId, 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!!"; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + memo: memo, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenMemoUpdate(mutableTokenId, memo); + }); + }); + + it("(#5) Updates a mutable token with a memo that exceeds the maximum length", async function () { + try { + await JSONRPCRequest(this, "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: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "MEMO_TOO_LONG"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Fee Schedule Key", function () { + it("(#1) Updates an immutable token with a valid key as its fee schedule key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + }); + + const key = response.key; + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + feeScheduleKey: key, + }); + } 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(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, publicKey, "feeScheduleKey"); + }); + }); + + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its fee schedule key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: publicKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, publicKey, "feeScheduleKey"); + }); + }); + + it("(#4) Updates a mutable token with a valid ED25519 private key as its fee schedule key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, publicKey, "feeScheduleKey"); + }); + }); + + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its fee schedule key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, publicKey, "feeScheduleKey"); + }); + }); + + 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( + this, + "generateKey", + fourKeysKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: keyList.key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenKeyList(mutableTokenId, keyList.key, "feeScheduleKey"); + }); + }); + + 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( + this, + "generateKey", + twoLevelsNestedKeyListParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: nestedKeyList.key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenKeyList(mutableTokenId, nestedKeyList.key, "feeScheduleKey"); + }); + }); + + 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( + this, + "generateKey", + twoThresholdKeyParams, + ); + + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: thresholdKey.key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenKeyList(mutableTokenId, thresholdKey.key, "feeScheduleKey"); + }); + }); + + it("(#9) Updates a mutable token with an empty KeyList as its fee schedule key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "keyList", + keys: [], + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenUpdateWithNullKey(mutableTokenId, "feeScheduleKey"); + }); + }); + + 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(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + const tokenId = response.tokenId; + + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: tokenId, + feeScheduleKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_FEE_SCHEDULE_KEY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#11) Updates a mutable token with an invalid key as its fee schedule key", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + describe("Pause Key", function () { + it("(#1) Updates an immutable token with a valid key as its pause key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + }); + + const key = response.key; + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + feeScheduleKey: key, + }); + } 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(this, "generateKey", { + type: "ed25519PublicKey", + }); + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, key, "pauseKey"); + }); + }); + + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its pause key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + }); + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, key, "pauseKey"); + }); + }); + + it("(#4) Updates a mutable token with a valid ED25519 private key as its pause key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, publicKey, "pauseKey"); + }); + }); + + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its pause key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, publicKey, "pauseKey"); + }); + }); + + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { + let response = await JSONRPCRequest( + this, + "generateKey", + fourKeysKeyListParams, + ); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenKeyList(mutableTokenId, key, "pauseKey"); + }); + }); + + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its pause key", async function () { + let response = await JSONRPCRequest( + this, + "generateKey", + twoLevelsNestedKeyListParams, + ); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenKeyList(mutableTokenId, key, "pauseKey"); + }); + }); + + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { + let response = await JSONRPCRequest( + this, + "generateKey", + twoThresholdKeyParams, + ); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenKeyList(mutableTokenId, key, "pauseKey"); + }); + }); + + it("(#9) Updates a mutable token with an empty KeyList as its pause key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "keyList", + keys: [], + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + pauseKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + await verifyTokenUpdateWithNullKey(mutableTokenId, "pauseKey"); + }); + }); + + 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(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + const tokenId = response.tokenId; + + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: tokenId, + pauseKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_PAUSE_KEY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#11) Updates a mutable token with an invalid key as its pause key", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + feeScheduleKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + 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, + ); + } + + it("(#1) Updates an immutable token with metadata", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + metadata: "1234", + }); + } catch (err) { + assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#2) Updates a mutable token with metadata", async function () { + const metadata = "1234"; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + metadata: metadata, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenMetadataUpdate(mutableTokenId, metadata); + }); + }); + + it("(#3) Updates a mutable token with empty metadata", async function () { + const metadata = ""; + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + metadata: metadata, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenMetadataUpdate(mutableTokenId, metadata); + }); + }); + }); + + describe("Metadata Key", function () { + it("(#1) Updates an immutable token with a valid key as its metadata key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + }); + + const key = response.key; + + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: immutableTokenId, + metadataKey: key, + }); + } 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(this, "generateKey", { + type: "ed25519PublicKey", + }); + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + metadataKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, key, "metadataKey"); + }); + }); + + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its metadata key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + }); + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + metadataKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, key, "metadataKey"); + }); + }); + + it("(#4) Updates a mutable token with a valid ED25519 private key as its metadata key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ed25519PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + metadataKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ED25519 public key DER-encoding has a 12 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, publicKey, "metadataKey"); + }); + }); + + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its metadata key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PrivateKey", + }); + + const privateKey = response.key; + + response = await JSONRPCRequest(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + fromKey: privateKey, + }); + const publicKey = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + metadataKey: privateKey, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + // Compare against raw key, ECDSAsecp256k1 public key DER-encoding has a 14 byte prefix. + await retryOnError(async () => { + verifyTokenKey(mutableTokenId, publicKey, "metadataKey"); + }); + }); + + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { + let response = await JSONRPCRequest( + this, + "generateKey", + fourKeysKeyListParams, + ); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + metadataKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenKeyList(mutableTokenId, key, "metadataKey"); + }); + }); + + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its metadata key", async function () { + let response = await JSONRPCRequest( + this, + "generateKey", + twoLevelsNestedKeyListParams, + ); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + metadataKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenKeyList(mutableTokenId, key, "metadataKey"); + }); + }); + + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { + let response = await JSONRPCRequest( + this, + "generateKey", + twoThresholdKeyParams, + ); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + metadataKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenKeyList(mutableTokenId, key, "metadataKey"); + }); + }); + + it("(#9) Updates a mutable token with an empty KeyList as its metadata key", async function () { + let response = await JSONRPCRequest(this, "generateKey", { + type: "keyList", + keys: [], + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + metadataKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + + await retryOnError(async () => { + verifyTokenUpdateWithNullKey(mutableTokenId, "metadataKey"); + }); + }); + + 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(this, "generateKey", { + type: "ecdsaSecp256k1PublicKey", + }); + + const key = response.key; + + response = await JSONRPCRequest(this, "createToken", { + name: initialTokenName, + symbol: initialTokenSymbol, + treasuryAccountId: initialTreasuryAccountId, + adminKey: mutableTokenKey, + initialSupply: initialSupply, + tokenType: "ft", + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + const tokenId = response.tokenId; + + try { + response = await JSONRPCRequest(this, "updateToken", { + tokenId: tokenId, + metadataKey: key, + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.data.status, "TOKEN_HAS_NO_METADATA_KEY"); + return; + } + + assert.fail("Should throw an error"); + }); + + it("(#11) Updates a mutable token with an invalid key as its metadata key", async function () { + try { + await JSONRPCRequest(this, "updateToken", { + tokenId: mutableTokenId, + metadataKey: crypto.randomBytes(88).toString("hex"), + commonTransactionParams: { + signers: [mutableTokenKey], + }, + }); + } catch (err) { + assert.equal(err.code, -32603, "Internal error"); + return; + } + + assert.fail("Should throw an error"); + }); + }); + + return Promise.resolve(); +}); 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, diff --git a/utils/helpers/verify-token-key.js b/utils/helpers/verify-token-tx.js similarity index 56% rename from utils/helpers/verify-token-key.js rename to utils/helpers/verify-token-tx.js index 8fc2e98..081aeb3 100644 --- a/utils/helpers/verify-token-key.js +++ b/utils/helpers/verify-token-tx.js @@ -1,10 +1,11 @@ import { expect } from "chai"; +import { Timestamp } from "@hashgraph/sdk"; -import { getRawKeyFromHex } from "../../utils/helpers/asn1-decoder.js"; +import { getRawKeyFromHex } from "./asn1-decoder.js"; import { getPublicKeyFromMirrorNode, getEncodedKeyHexFromKeyListConsensus, -} from "../../utils/helpers/key.js"; +} from "./key.js"; import mirrorNodeClient from "../../mirrorNodeClient.js"; import consensusInfoClient from "../../consensusInfoClient.js"; @@ -61,3 +62,45 @@ export async function verifyTokenKeyList(tokenId, key, keyType) { function transformConsensusToMirrorNodeProp(key) { return key.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase(); } + +export async function verifyTokenUpdateWithNullKey(tokenId, keyType) { + // Fetch the key from the consensus node and check if it is null + const consensusNodeKey = await ( + await consensusInfoClient.getTokenInfo(tokenId) + )[keyType]; + expect(null).to.equal(consensusNodeKey); + + // Convert the keyType to match the mirror node property format + const mirrorNodeKeyName = transformConsensusToMirrorNodeProp(keyType); + + // Fetch the key from the mirror node and check if it is null + const mirrorNodeKey = await getPublicKeyFromMirrorNode( + "getTokenData", + tokenId, + mirrorNodeKeyName, + ); + expect(null).to.equal(mirrorNodeKey); +} + +export async function verifyTokenExpirationTimeUpdate(tokenId, expirationTime) { + 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); +} From 551e7e7ea5b7a426ef4938082708c5209bdc5ae6 Mon Sep 17 00:00:00 2001 From: Rob Walworth <110835868+rwalworth@users.noreply.github.com> Date: Wed, 20 Nov 2024 11:10:37 -0500 Subject: [PATCH 04/12] docs: Add test specifications for `TokenPauseTransaction` (#266) Signed-off-by: Rob Walworth --- .../token-service/tokenPauseTransaction.md | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 test-specifications/token-service/tokenPauseTransaction.md diff --git a/test-specifications/token-service/tokenPauseTransaction.md b/test-specifications/token-service/tokenPauseTransaction.md new file mode 100644 index 0000000..bb4b092 --- /dev/null +++ b/test-specifications/token-service/tokenPauseTransaction.md @@ -0,0 +1,93 @@ +# TokenPauseTransaction - Test specification + +## Description: +This test specification for TokenPauseTransaction is to be one of many for testing the functionality of the Hedera SDKs. The SDK under test will use the language specific JSON-RPC server return responses back to the test driver. + +## Design: +Each test within the test specification is linked to one of the properties within TokenPauseTransaction. Each property is tested with a mix of boundaries. The inputs for each test are a range of valid, minimum, maximum, negative and invalid values for the method. The expected response of a passed test can be a correct error response code or seen as the result of node queries. A successful transaction (the transaction reached consensus and was applied to state) can be determined by getting a `TransactionReceipt` or `TransactionRecord`, or can be determined by using queries such as `TokenInfoQuery` or `TokenBalanceQuery` and investigating for the required changes (creations, updates, etc.). The mirror node can also be used to determine if a transaction was successful via its rest API. Error codes are obtained from the response code proto files. + +**Transaction properties:** + +https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/pause-a-token + +**TokenPause protobufs:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/token_pause.proto + +**Response codes:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto + +**Mirror Node APIs:** + +https://docs.hedera.com/hedera/sdks-and-apis/rest-api + +## JSON-RPC API Endpoint Documentation + +### Method Name + +`pauseToken` + +### Input Parameters + +| Parameter Name | Type | Required/Optional | Description/Notes | +|-------------------------|--------------------------------------------------|-------------------|-------------------------------| +| tokenId | string | optional | The ID of the token to pause. | +| commonTransactionParams | [json object](../commonTransactionParameters.md) | optional | | + +### Output Parameters + +| Parameter Name | Type | Description/Notes | +|----------------|--------|------------------------------------------------------------------------------------| +| status | string | The status of the submitted `TokenPauseTransaction` (from a `TransactionReceipt`). | + +### Additional Notes + +The tests contained in this specification will assume that a valid token has already been created. will denote the ID of the token, will denote the pause key of the token as a DER-encoded hex string, and will denote the admin key of the token as a DER-encoded hex string. + +## Property Tests + +### **Token ID:** + +- The ID of the token to pause. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|---------------------------------------------------------------------|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------|-------------------| +| 1 | Pauses a token | tokenId=, commonTransactionParams.signers=[] | The token pause succeeds and the token is paused. | N | +| 2 | Pauses a token with no token ID | | The token pause fails with an INVALID_TOKEN_ID response code from the network. | N | +| 3 | Pauses a token without signing with the token's pause key | tokenId= | The token pause fails with an INVALID_SIGNATURE response code from the network. | N | +| 4 | Pauses a token and sign with the admin key instead of the pause key | tokenId=, commonTransactionParams.signers=[] | The token pause fails with an INVALID_SIGNATURE response code from the network. | N | +| 5 | Pauses a token that doesn't exist | tokenId="123.456.789" | The token pause fails with an INVALID_TOKEN_ID response code from the network. | N | +| 6 | Pauses a token that is deleted | tokenId=, commonTransactionParams.signers=[] | The token pause fails with an TOKEN_WAS_DELETED response code from the network. | N | +| 7 | Pauses a token that is empty | tokenId="" | The token pause fails with an SDK internal error. | N | +| 8 | Pauses a token twice | tokenId=, commonTransactionParams.signers=[] | The token pause fails with an TOKEN_IS_PAUSED response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "method": "pauseToken", + "params": { + "tokenId": "0.0.2533", + "commonTransactionParams": { + "signers": [ + "302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "result": { + "status": "SUCCESS" + } +} +``` \ No newline at end of file From 9400436a5f2f068b6f62d4403c570ddb4520a852 Mon Sep 17 00:00:00 2001 From: Rob Walworth <110835868+rwalworth@users.noreply.github.com> Date: Wed, 20 Nov 2024 11:28:02 -0500 Subject: [PATCH 05/12] docs: Add test specifications for `TokenUnpauseTransaction` (#267) Signed-off-by: Rob Walworth --- .../token-service/tokenUnpauseTransaction.md | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 test-specifications/token-service/tokenUnpauseTransaction.md diff --git a/test-specifications/token-service/tokenUnpauseTransaction.md b/test-specifications/token-service/tokenUnpauseTransaction.md new file mode 100644 index 0000000..6bdb88d --- /dev/null +++ b/test-specifications/token-service/tokenUnpauseTransaction.md @@ -0,0 +1,93 @@ +# TokenUnpauseTransaction - Test specification + +## Description: +This test specification for TokenUnpauseTransaction is to be one of many for testing the functionality of the Hedera SDKs. The SDK under test will use the language specific JSON-RPC server return responses back to the test driver. + +## Design: +Each test within the test specification is linked to one of the properties within TokenUnpauseTransaction. Each property is tested with a mix of boundaries. The inputs for each test are a range of valid, minimum, maximum, negative and invalid values for the method. The expected response of a passed test can be a correct error response code or seen as the result of node queries. A successful transaction (the transaction reached consensus and was applied to state) can be determined by getting a `TransactionReceipt` or `TransactionRecord`, or can be determined by using queries such as `TokenInfoQuery` or `TokenBalanceQuery` and investigating for the required changes (creations, updates, etc.). The mirror node can also be used to determine if a transaction was successful via its rest API. Error codes are obtained from the response code proto files. + +**Transaction properties:** + +https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/unpause-a-token + +**TokenUnpause protobufs:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/token_unpause.proto + +**Response codes:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto + +**Mirror Node APIs:** + +https://docs.hedera.com/hedera/sdks-and-apis/rest-api + +## JSON-RPC API Endpoint Documentation + +### Method Name + +`unpauseToken` + +### Input Parameters + +| Parameter Name | Type | Required/Optional | Description/Notes | +|-------------------------|--------------------------------------------------|-------------------|---------------------------------| +| tokenId | string | optional | The ID of the token to unpause. | +| commonTransactionParams | [json object](../commonTransactionParameters.md) | optional | | + +### Output Parameters + +| Parameter Name | Type | Description/Notes | +|----------------|--------|--------------------------------------------------------------------------------------| +| status | string | The status of the submitted `TokenUnpauseTransaction` (from a `TransactionReceipt`). | + +### Additional Notes + +The tests contained in this specification will assume that a valid token has already been created and paused, unless specified otherwise. will denote the ID of the token, will denote the pause key of the token as a DER-encoded hex string, and will denote the admin key of the token as a DER-encoded hex string. + +## Property Tests + +### **Token ID:** + +- The ID of the token to unpause. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|-----------------------------------------------------------------------|-----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|-------------------| +| 1 | Unpauses a token | tokenId=, commonTransactionParams.signers=[] | The token unpause succeeds and the token is unpaused. | N | +| 2 | Unpauses a token with no token ID | | The token unpause fails with an INVALID_TOKEN_ID response code from the network. | N | +| 3 | Unpauses a token without signing with the token's pause key | tokenId= | The token unpause fails with an INVALID_SIGNATURE response code from the network. | N | +| 4 | Unpauses a token and sign with the admin key instead of the pause key | tokenId=, commonTransactionParams.signers=[] | The token unpause fails with an INVALID_SIGNATURE response code from the network. | N | +| 5 | Unpauses a token that doesn't exist | tokenId="123.456.789" | The token unpause fails with an INVALID_TOKEN_ID response code from the network. | N | +| 6 | Unpauses a token that is deleted | tokenId=, commonTransactionParams.signers=[] | The token unpause fails with an TOKEN_WAS_DELETED response code from the network. | N | +| 7 | Unpauses a token that is empty | tokenId="" | The token unpause fails with an SDK internal error. | N | +| 8 | Unpauses a token that isn't paused | tokenId=, commonTransactionParams.signers=[] | The token unpause succeeds and the token is unpaused. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "method": "unpauseToken", + "params": { + "tokenId": "0.0.2533", + "commonTransactionParams": { + "signers": [ + "302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "result": { + "status": "SUCCESS" + } +} +``` \ No newline at end of file From 6836a32eafed907ba3225c1a708d673e6f1a3750 Mon Sep 17 00:00:00 2001 From: Rob Walworth <110835868+rwalworth@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:42:06 -0500 Subject: [PATCH 06/12] docs: Add test specifications for `TokenDissociateTransaction` (#265) Signed-off-by: Rob Walworth --- .../tokenDisscoiateTransaction.md | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 test-specifications/token-service/tokenDisscoiateTransaction.md diff --git a/test-specifications/token-service/tokenDisscoiateTransaction.md b/test-specifications/token-service/tokenDisscoiateTransaction.md new file mode 100644 index 0000000..4f5d1f7 --- /dev/null +++ b/test-specifications/token-service/tokenDisscoiateTransaction.md @@ -0,0 +1,148 @@ +# TokenDissociateTransaction - Test specification + +## Description: +This test specification for TokenDissociateTransaction is to be one of many for testing the functionality of the Hedera SDKs. The SDK under test will use the language specific JSON-RPC server return responses back to the test driver. + +## Design: +Each test within the test specification is linked to one of the properties within TokenDissociateTransaction. Each property is tested with a mix of boundaries. The inputs for each test are a range of valid, minimum, maximum, negative and invalid values for the method. The expected response of a passed test can be a correct error response code or seen as the result of node queries. A successful transaction (the transaction reached consensus and was applied to state) can be determined by getting a `TransactionReceipt` or `TransactionRecord`, or can be determined by using queries such as `TokenInfoQuery` or `TokenBalanceQuery` and investigating for the required changes (creations, updates, etc.). The mirror node can also be used to determine if a transaction was successful via its rest API. Error codes are obtained from the response code proto files. + +**Transaction properties:** + +https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/dissociate-tokens-from-an-account + +**TokenDissociate protobufs:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/token_dissociate.proto + +**Response codes:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto + +**Mirror Node APIs:** + +https://docs.hedera.com/hedera/sdks-and-apis/rest-api + +## JSON-RPC API Endpoint Documentation + +### Method Name + +`dissociateToken` + +### Input Parameters + +| Parameter Name | Type | Required/Optional | Description/Notes | +|-------------------------|--------------------------------------------------|-------------------|---------------------------------------------------------| +| accountId | string | optional | The ID of the account from which to dissociate a token. | +| tokenIds | list | optional | The IDs of the tokens to dissociate. | +| commonTransactionParams | [json object](../commonTransactionParameters.md) | optional | | + +### Output Parameters + +| Parameter Name | Type | Description/Notes | +|----------------|--------|-----------------------------------------------------------------------------------------| +| status | string | The status of the submitted `TokenDissociateTransaction` (from a `TransactionReceipt`). | + +### Additional Notes + +The tests contained in this specification will assume that a valid account and a valid token were already successfully created and associated. will denote the ID of the account, and will denote the private key of the account as a DER-encoded hex string. The token shall be created with default values name="testname", symbol="testsymbol", treasuryAccountId=, and tokenType="ft". will denote the ID of the created token. The account will only need to be created once, but a new token should be created and associated for each test. + +## Property Tests + +### **Account ID:** + +- The ID of the account from which to dissociate a token. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|-------------------| +| 1 | Dissociates a token from an account | accountId=, tokenIds=[], commonTransactionParams.signers=[] | The token dissociation succeeds and the token is associated with . | N | +| 2 | Dissociates a token from an account with which it is already dissociated | accountId=, tokenIds=[], commonTransactionParams.signers=[] | The token dissociation fails with an TOKEN_NOT_ASSOCIATED_TO_ACCOUNT response code from the network. | N | +| 3 | Dissociates a token from an account without signing with the account's private key | accountId=, tokenIds=[] | The token dissociation fails with an INVALID_SIGNATURE response code from the network. | N | +| 4 | Dissociates a token from an account that doesn't exist | accountId="123.456.789", tokenIds=[] | The token dissociation fails with an INVALID_ACCOUNT_ID response code from the network. | N | +| 5 | Dissociates a token from an account that is deleted | accountId=, tokenIds=[], commonTransactionParams.signers=[] | The token dissociation fails with an INVALID_ACCOUNT_ID response code from the network. | N | +| 6 | Dissociates a token from an empty account | accountId="", tokenIds=[] | The token dissociation fails with an SDK internal error. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "method": "dissociateToken", + "params": { + "accountId": "0.0.2533", + "tokenIds": [ + "0.0.579680", + "0.0.90649" + ], + "commonTransactionParams": { + "signers": [ + "302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "result": { + "status": "SUCCESS" + } +} +``` + +### **Token IDs:** + +- The IDs of the tokens to dissociate. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|-----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|-------------------| +| 1 | Dissociates no tokens from an account | accountId=, commonTransactionParams.signers=[] | The token dissociation succeeds and no disassociations are made. | N | +| 2 | Dissociates a token that doesn't exist from an account | accountId=, tokenIds=["123.456.789"], commonTransactionParams.signers=[] | The token dissociation fails with an INVALID_TOKEN_ID response code from the network. | N | +| 3 | Dissociates a token that is deleted from an account | accountId=, tokenIds=[], commonTransactionParams.signers=[] | The token dissociation fails with an TOKEN_WAS_DELETED response code from the network. | N | +| 4 | Dissociates a token that is empty from an account | accountId=, tokenIds=[""], commonTransactionParams.signers=[] | The token dissociation fails with an SDK internal error. | N | +| 5 | Dissociates a token twice from an account | accountId=, tokenIds=[, ], commonTransactionParams.signers=[] | The token dissociation fails with an TOKEN_ID_REPEATED_IN_TOKEN_LIST response code from the network. | N | +| 6 | Dissociates three valid tokens from an account | accountId=, tokenIds=[, , ], commonTransactionParams.signers=[] | The token dissociation succeeds and three disassociations are made. | N | +| 7 | Dissociates two valid tokens and an invalid token from an account | accountId=, tokenIds=[, , "123.456.789"], commonTransactionParams.signers=[] | The token dissociation fails with an INVALID_TOKEN_ID response code from the network. | N | +| 8 | Dissociates two valid tokens and a deleted token from an account | accountId=, tokenIds=[, , ], commonTransactionParams.signers=[] | The token dissociation fails with an TOKEN_WAS_DELETED response code from the network. | N | +| 9 | Dissociates a token from an account while that account has a balance of the token | accountId=, tokenIds=[], commonTransactionParams.signers=[] | The token dissociation fails with an TRANSACTION_REQUIRES_ZERO_TOKEN_BALANCES response code from the network. | N | +| 10 | Dissociates a token from an account while its frozen for the account | accountId=, tokenIds=[], commonTransactionParams.signers=[] | The token dissociation fails with an ACCOUNT_FROZEN_FOR_TOKEN response code from the network. | N | +| 11 | Dissociates a token from an account while the token is paused | accountId=, tokenIds=[], commonTransactionParams.signers=[] | The token dissociation fails with an TOKEN_IS_PAUSED response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "method": "dissociateToken", + "params": { + "accountId": "0.0.2533", + "tokenIds": [ + "0.0.579680", + "0.0.90649" + ], + "commonTransactionParams": { + "signers": [ + "302e020100300506032b65700422042031f8eb3e77a04ebe599c51570976053009e619414f26bdd39676a5d3b2782a1d" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 99232, + "result": { + "status": "SUCCESS" + } +} +``` From c9f507309e33f31ef8e2bd12846d2556af967756 Mon Sep 17 00:00:00 2001 From: Rob Walworth <110835868+rwalworth@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:29:04 -0500 Subject: [PATCH 07/12] docs: Add test specifications for `TokenGrantKycTransaction` (#269) Signed-off-by: Rob Walworth --- .../token-service/tokenGrantKycTransaction.md | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 test-specifications/token-service/tokenGrantKycTransaction.md diff --git a/test-specifications/token-service/tokenGrantKycTransaction.md b/test-specifications/token-service/tokenGrantKycTransaction.md new file mode 100644 index 0000000..2e62866 --- /dev/null +++ b/test-specifications/token-service/tokenGrantKycTransaction.md @@ -0,0 +1,142 @@ +# TokenGrantKycTransaction - Test specification + +## Description: +This test specification for TokenGrantKycTransaction is to be one of many for testing the functionality of the Hedera SDKs. The SDK under test will use the language specific JSON-RPC server return responses back to the test driver. + +## Design: +Each test within the test specification is linked to one of the properties within TokenGrantKycTransaction. Each property is tested with a mix of boundaries. The inputs for each test are a range of valid, minimum, maximum, negative and invalid values for the method. The expected response of a passed test can be a correct error response code or seen as the result of node queries. A successful transaction (the transaction reached consensus and was applied to state) can be determined by getting a `TransactionReceipt` or `TransactionRecord`, or can be determined by using queries such as `TokenInfoQuery` or `AccountBalanceQuery` and investigating for the required changes (creations, updates, etc.). The mirror node can also be used to determine if a transaction was successful via its rest API. Error codes are obtained from the response code proto files. + +**Transaction properties:** + +https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/enable-kyc-account-flag + +**TokenGrantKyc protobufs:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/token_grant_kyc.proto + +**Response codes:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto + +**Mirror Node APIs:** + +https://docs.hedera.com/hedera/sdks-and-apis/rest-api + +## JSON-RPC API Endpoint Documentation + +### Method Name + +`grantTokenKyc` + +### Input Parameters + +| Parameter Name | Type | Required/Optional | Description/Notes | +|-------------------------|--------------------------------------------------|-------------------|----------------------------------------------| +| tokenId | string | optional | The ID of the token of which to grant KYC. | +| accountId | string | optional | The ID of the account to which to grant KYC. | +| commonTransactionParams | [json object](../commonTransactionParameters.md) | optional | | + +### Output Parameters + +| Parameter Name | Type | Description/Notes | +|----------------|--------|---------------------------------------------------------------------------------------| +| status | string | The status of the submitted `TokenGrantKycTransaction` (from a `TransactionReceipt`). | + +### Additional Notes + +The tests contained in this specification will assume that a valid account and a valid token have already successfully created and associated. will denote the ID of the account, and will denote the private key of the created account as a DER-encoded hex string. will denote the ID of the created token, will denote the KYC key of the token as a DER-encoded hex string, and will denote the admin key of the token as a DER-encoded hex string. + +## Property Tests + +### **Token ID:** + +- The ID of the token of which to grant KYC. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|-------------------| +| 1 | Grants KYC of a token to an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token grants KYC to the account. | N | +| 2 | Grants KYC of a token that doesn't exist to an account | tokenId="123.456.789", accountId= | The token KYC grant fails with an INVALID_TOKEN_ID response code from the network. | N | +| 3 | Grants KYC of a token with an empty token ID to an account | tokenId="", accountId= | The token KYC grant fails with an SDK internal error. | N | +| 4 | Grants KYC of a token with no token ID to an account | accountId= | The token KYC grant fails with an INVALID_TOKEN_ID response code from the network. | N | +| 5 | Grants KYC of a deleted token to an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC grant fails with an TOKEN_WAS_DELETED response code from the network. | N | +| 6 | Grants KYC of a token to an account without signing with the token's KYC key | tokenId=, accountId= | The token KYC grant fails with an INVALID_SIGNATURE response code from the network. | N | +| 7 | Grants KYC of a token to an account but signs with the the token's admin key | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC grant fails with an INVALID_SIGNATURE response code from the network. | N | +| 8 | Grants KYC of a token to an account but signs with an incorrect private key | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC grant fails with an INVALID_SIGNATURE response code from the network. | N | +| 9 | Grants KYC of a token with no KYC key to an account | tokenId=, accountId= | The token KYC grant fails with an TOKEN_HAS_NO_KYC_KEY response code from the network. | N | +| 10 | Grants KYC of a token to an account that already has KYC | tokenId=, accountId=, commonTransactionParams.signers=[] | The token grants KYC to the account. | N | +| 11 | Grants KYC of a token to an account that is not associated with the token | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC grant fails with an TOKEN_NOT_ASSOCIATED_TO_ACCOUNT response code from the network. | N | +| 12 | Grants KYC of a paused token to an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC grant fails with an TOKEN_IS_PAUSED response code from the network. | N | +| 13 | Grants KYC of a token to a frozen account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC grant fails with an ACCOUNT_FROZEN_FOR_TOKEN response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "method": "grantTokenKyc", + "params": { + "tokenId": "0.0.15432", + "accountId": "0.0.53848", + "commonTransactionParams": { + "signers": [ + "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "result": { + "status": "SUCCESS" + } +} +``` + +### **Account ID:** + +- The ID of the account to which to grant KYC. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|--------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|-------------------| +| 1 | Grants KYC of a token to an account that doesn't exist | tokenId=, accountId="123.456.789", commonTransactionParams.signers=[] | The token KYC grant fails with an INVALID_ACCOUNT_ID response code from the network. | N | +| 2 | Grants KYC of a token to an empty account ID | tokenId=, accountId="", commonTransactionParams.signers=[] | The token KYC grant fails with an SDK internal error. | N | +| 3 | Grants KYC of a token to an account with no account ID | tokenId=, commonTransactionParams.signers=[] | The token KYC grant fails with an INVALID_ACCOUNT_ID response code from the network. | N | +| 4 | Grants KYC of a token to a deleted account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC grant fails with an ACCOUNT_WAS_DELETED response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "method": "grantTokenKyc", + "params": { + "tokenId": "0.0.15432", + "accountId": "0.0.53848", + "commonTransactionParams": { + "signers": [ + "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "result": { + "status": "SUCCESS" + } +} +``` From baadeb295bdf96381cbf45f4b9765516091e35ab Mon Sep 17 00:00:00 2001 From: Rob Walworth <110835868+rwalworth@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:36:39 -0500 Subject: [PATCH 08/12] docs: Add test specifications for `TokenRevokeKycTransaction` (#270) Signed-off-by: Rob Walworth --- .../tokenRevokeKycTransaction.md | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 test-specifications/token-service/tokenRevokeKycTransaction.md diff --git a/test-specifications/token-service/tokenRevokeKycTransaction.md b/test-specifications/token-service/tokenRevokeKycTransaction.md new file mode 100644 index 0000000..1de9990 --- /dev/null +++ b/test-specifications/token-service/tokenRevokeKycTransaction.md @@ -0,0 +1,142 @@ +# TokenRevokeKycTransaction - Test specification + +## Description: +This test specification for TokenRevokeKycTransaction is to be one of many for testing the functionality of the Hedera SDKs. The SDK under test will use the language specific JSON-RPC server return responses back to the test driver. + +## Design: +Each test within the test specification is linked to one of the properties within TokenRevokeKycTransaction. Each property is tested with a mix of boundaries. The inputs for each test are a range of valid, minimum, maximum, negative and invalid values for the method. The expected response of a passed test can be a correct error response code or seen as the result of node queries. A successful transaction (the transaction reached consensus and was applied to state) can be determined by getting a `TransactionReceipt` or `TransactionRecord`, or can be determined by using queries such as `TokenInfoQuery` or `AccountBalanceQuery` and investigating for the required changes (creations, updates, etc.). The mirror node can also be used to determine if a transaction was successful via its rest API. Error codes are obtained from the response code proto files. + +**Transaction properties:** + +https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/disable-kyc-account-flag + +**TokenGrantKyc protobufs:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/token_revoke_kyc.proto + +**Response codes:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto + +**Mirror Node APIs:** + +https://docs.hedera.com/hedera/sdks-and-apis/rest-api + +## JSON-RPC API Endpoint Documentation + +### Method Name + +`revokeTokenKyc` + +### Input Parameters + +| Parameter Name | Type | Required/Optional | Description/Notes | +|-------------------------|--------------------------------------------------|-------------------|-----------------------------------------------| +| tokenId | string | optional | The ID of the token of which to revoke KYC. | +| accountId | string | optional | The ID of the account to which to revoke KYC. | +| commonTransactionParams | [json object](../commonTransactionParameters.md) | optional | | + +### Output Parameters + +| Parameter Name | Type | Description/Notes | +|----------------|--------|----------------------------------------------------------------------------------------| +| status | string | The status of the submitted `TokenRevokeKycTransaction` (from a `TransactionReceipt`). | + +### Additional Notes + +The tests contained in this specification will assume that a valid account has been granted KYC for a valid token. will denote the ID of the account, and will denote the private key of the created account as a DER-encoded hex string. will denote the ID of the created token, will denote the KYC key of the token as a DER-encoded hex string, and will denote the admin key of the token as a DER-encoded hex string. + +## Property Tests + +### **Token ID:** + +- The ID of the token of which to revoke KYC. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|-------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------|-------------------| +| 1 | Revokes KYC of a token to an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token revokes KYC to the account. | N | +| 2 | Revokes KYC of a token that doesn't exist to an account | tokenId="123.456.789", accountId= | The token KYC revoke fails with an INVALID_TOKEN_ID response code from the network. | N | +| 3 | Revokes KYC of a token with an empty token ID to an account | tokenId="", accountId= | The token KYC revoke fails with an SDK internal error. | N | +| 4 | Revokes KYC of a token with no token ID to an account | accountId= | The token KYC revoke fails with an INVALID_TOKEN_ID response code from the network. | N | +| 5 | Revokes KYC of a deleted token to an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC revoke fails with an TOKEN_WAS_DELETED response code from the network. | N | +| 6 | Revokes KYC of a token to an account without signing with the token's KYC key | tokenId=, accountId= | The token KYC revoke fails with an INVALID_SIGNATURE response code from the network. | N | +| 7 | Revokes KYC of a token to an account but signs with the the token's admin key | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC revoke fails with an INVALID_SIGNATURE response code from the network. | N | +| 8 | Revokes KYC of a token to an account but signs with an incorrect private key | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC revoke fails with an INVALID_SIGNATURE response code from the network. | N | +| 9 | Revokes KYC of a token with no KYC key to an account | tokenId=, accountId= | The token KYC revoke fails with an TOKEN_HAS_NO_KYC_KEY response code from the network. | N | +| 10 | Revokes KYC of a token to an account that doesn't have KYC | tokenId=, accountId=, commonTransactionParams.signers=[] | The token revokes KYC to the account. | N | +| 11 | Revokes KYC of a token to an account that is not associated with the token | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC revoke fails with an TOKEN_NOT_ASSOCIATED_TO_ACCOUNT response code from the network. | N | +| 12 | Revokes KYC of a paused token to an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC revoke fails with an TOKEN_IS_PAUSED response code from the network. | N | +| 13 | Revokes KYC of a token to a frozen account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC revoke fails with an ACCOUNT_FROZEN_FOR_TOKEN response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "method": "revokeTokenKyc", + "params": { + "tokenId": "0.0.15432", + "accountId": "0.0.53848", + "commonTransactionParams": { + "signers": [ + "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "result": { + "status": "SUCCESS" + } +} +``` + +### **Account ID:** + +- The ID of the account to which to revoke KYC. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|---------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|-------------------| +| 1 | Revokes KYC of a token to an account that doesn't exist | tokenId=, accountId="123.456.789", commonTransactionParams.signers=[] | The token KYC revoke fails with an INVALID_ACCOUNT_ID response code from the network. | N | +| 2 | Revokes KYC of a token to an empty account ID | tokenId=, accountId="", commonTransactionParams.signers=[] | The token KYC revoke fails with an SDK internal error. | N | +| 3 | Revokes KYC of a token to an account with no account ID | tokenId=, commonTransactionParams.signers=[] | The token KYC revoke fails with an INVALID_TOKEN_ID response code from the network. | N | +| 4 | Revokes KYC of a token to a deleted account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token KYC revoke fails with an ACCOUNT_WAS_DELETED response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "method": "revokeTokenKyc", + "params": { + "tokenId": "0.0.15432", + "accountId": "0.0.53848", + "commonTransactionParams": { + "signers": [ + "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "result": { + "status": "SUCCESS" + } +} +``` From c2bb15f04105f242865aa05748d9282cc59d7be1 Mon Sep 17 00:00:00 2001 From: Rob Walworth <110835868+rwalworth@users.noreply.github.com> Date: Wed, 4 Dec 2024 11:46:39 -0500 Subject: [PATCH 09/12] docs: Add test specifications for `TokenFreezeTransaction` (#273) Signed-off-by: Rob Walworth --- .../token-service/tokenFreezeTransaction.md | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 test-specifications/token-service/tokenFreezeTransaction.md diff --git a/test-specifications/token-service/tokenFreezeTransaction.md b/test-specifications/token-service/tokenFreezeTransaction.md new file mode 100644 index 0000000..2ed7005 --- /dev/null +++ b/test-specifications/token-service/tokenFreezeTransaction.md @@ -0,0 +1,141 @@ +# TokenFreezeTransaction - Test specification + +## Description: +This test specification for TokenFreezeTransaction is to be one of many for testing the functionality of the Hedera SDKs. The SDK under test will use the language specific JSON-RPC server return responses back to the test driver. + +## Design: +Each test within the test specification is linked to one of the properties within TokenFreezeTransaction. Each property is tested with a mix of boundaries. The inputs for each test are a range of valid, minimum, maximum, negative and invalid values for the method. The expected response of a passed test can be a correct error response code or seen as the result of node queries. A successful transaction (the transaction reached consensus and was applied to state) can be determined by getting a `TransactionReceipt` or `TransactionRecord`, or can be determined by using queries such as `TokenInfoQuery` or `AccountBalanceQuery` and investigating for the required changes (creations, updates, etc.). The mirror node can also be used to determine if a transaction was successful via its rest API. Error codes are obtained from the response code proto files. + +**Transaction properties:** + +https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/freeze-an-account + +**TokenDelete protobufs:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/token_freeze_account.proto + +**Response codes:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto + +**Mirror Node APIs:** + +https://docs.hedera.com/hedera/sdks-and-apis/rest-api + +## JSON-RPC API Endpoint Documentation + +### Method Name + +`freezeToken` + +### Input Parameters + +| Parameter Name | Type | Required/Optional | Description/Notes | +|-------------------------|--------------------------------------------------|-------------------|----------------------------------| +| tokenId | string | optional | The ID of the token to freeze. | +| accountId | string | optional | The ID of the account to freeze. | +| commonTransactionParams | [json object](../commonTransactionParameters.md) | optional | | + +### Output Parameters + +| Parameter Name | Type | Description/Notes | +|----------------|--------|-------------------------------------------------------------------------------------| +| status | string | The status of the submitted `TokenFreezeTransaction` (from a `TransactionReceipt`). | + +### Additional Notes + +The tests contained in this specification will assume that a valid account and a valid token have already successfully created and associated, unless otherwise specified. will denote the ID of the account, and will denote the private key of the created account as a DER-encoded hex string. will denote the ID of the created token, will denote the freeze key of the token as a DER-encoded hex string, and will denote the admin key of the token as a DER-encoded hex string. + +## Property Tests + +### **Token ID:** + +- The ID of the token to freeze. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|---------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|-------------------| +| 1 | Freezes a token on an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token freeze succeeds. | N | +| 2 | Freezes a token that doesn't exist on an account | tokenId="123.456.789", accountId= | The token freeze fails with an INVALID_TOKEN_ID response code from the network. | N | +| 3 | Freezes a token with an empty token ID on an account | tokenId="", accountId= | The token freeze fails with an SDK internal error. | N | +| 4 | Freezes a token with no token ID on an account | accountId= | The token freeze fails with an INVALID_TOKEN_ID response code from the network. | N | +| 5 | Freezes a deleted token on an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token freeze fails with an TOKEN_WAS_DELETED response code from the network. | N | +| 6 | Freezes a token on an account without signing with the token's freeze key | tokenId=, accountId= | The token freeze fails with an INVALID_SIGNATURE response code from the network. | N | +| 7 | Freezes a token but signs with the token's admin key | tokenId=, accountId=, commonTransactionParams.signers=[] | The token freeze fails with an INVALID_SIGNATURE response code from the network. | N | +| 8 | Freezes a token on an account but signs with an incorrect freeze key | tokenId=, accountId=, commonTransactionParams.signers=[] | The token freeze fails with an INVALID_SIGNATURE response code from the network. | N | +| 9 | Freezes a token with no freeze key on an account | tokenId=, accountId= | The token freeze fails with an TOKEN_HAS_NO_FREEZE_KEY response code from the network. | N | +| 10 | Freezes a token that is already frozen on an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token freeze succeeds. | N | +| 11 | Freezes a token on an account that is not associated with the token | tokenId=, accountId=, commonTransactionParams.signers=[] | The token freeze fails with an TOKEN_NOT_ASSOCIATED_WITH_ACCOUNT response code from the network. | N | +| 12 | Freezes a paused token on an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token freeze fails with an TOKEN_IS_PAUSED response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "method": "freezeToken", + "params": { + "tokenId": "0.0.15432", + "accountId": "0.0.54811", + "commonTransactionParams": { + "signers": [ + "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "result": { + "status": "SUCCESS" + } +} +``` + +### **Account ID:** + +- The ID of the account to freeze. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|---------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|-------------------| +| 1 | Freezes a token on an account that doesn't exist | tokenId=, accountId="123.456.789", commonTransactionParams.signers=[] | The token freeze fails with an INVALID_ACCOUNT_ID response code from the network. | N | +| 2 | Freezes a token on an account with an empty account ID | tokenId=, accountId="", commonTransactionParams.signers=[] | The token freeze fails with an SDK internal error. | N | +| 3 | Freezes a token on an account with no account ID | tokenId=, commonTransactionParams.signers=[] | The token freeze fails with an INVALID_ACCOUNT_ID response code from the network. | N | +| 4 | Freezes a token on a deleted account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token freeze fails with an ACCOUNT_WAS_DELETED response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "method": "freezeToken", + "params": { + "tokenId": "0.0.15432", + "accountId": "0.0.54811", + "commonTransactionParams": { + "signers": [ + "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "result": { + "status": "SUCCESS" + } +} +``` From be374e3f312009949a2fc349649b956520ac4b8a Mon Sep 17 00:00:00 2001 From: Rob Walworth <110835868+rwalworth@users.noreply.github.com> Date: Wed, 4 Dec 2024 11:46:53 -0500 Subject: [PATCH 10/12] docs: Add test specifications for `TokenUnfreezeTransaction` (#274) Signed-off-by: Rob Walworth --- .../token-service/tokenUnfreezeTransaction.md | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 test-specifications/token-service/tokenUnfreezeTransaction.md diff --git a/test-specifications/token-service/tokenUnfreezeTransaction.md b/test-specifications/token-service/tokenUnfreezeTransaction.md new file mode 100644 index 0000000..e988463 --- /dev/null +++ b/test-specifications/token-service/tokenUnfreezeTransaction.md @@ -0,0 +1,141 @@ +# TokenUnfreezeTransaction - Test specification + +## Description: +This test specification for TokenUnfreezeTransaction is to be one of many for testing the functionality of the Hedera SDKs. The SDK under test will use the language specific JSON-RPC server return responses back to the test driver. + +## Design: +Each test within the test specification is linked to one of the properties within TokenUnfreezeTransaction. Each property is tested with a mix of boundaries. The inputs for each test are a range of valid, minimum, maximum, negative and invalid values for the method. The expected response of a passed test can be a correct error response code or seen as the result of node queries. A successful transaction (the transaction reached consensus and was applied to state) can be determined by getting a `TransactionReceipt` or `TransactionRecord`, or can be determined by using queries such as `TokenInfoQuery` or `AccountBalanceQuery` and investigating for the required changes (creations, updates, etc.). The mirror node can also be used to determine if a transaction was successful via its rest API. Error codes are obtained from the response code proto files. + +**Transaction properties:** + +https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/unfreeze-an-account + +**TokenDelete protobufs:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/token_unfreeze_account.proto + +**Response codes:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto + +**Mirror Node APIs:** + +https://docs.hedera.com/hedera/sdks-and-apis/rest-api + +## JSON-RPC API Endpoint Documentation + +### Method Name + +`unfreezeToken` + +### Input Parameters + +| Parameter Name | Type | Required/Optional | Description/Notes | +|-------------------------|--------------------------------------------------|-------------------|------------------------------------| +| tokenId | string | optional | The ID of the token to unfreeze. | +| accountId | string | optional | The ID of the account to unfreeze. | +| commonTransactionParams | [json object](../commonTransactionParameters.md) | optional | | + +### Output Parameters + +| Parameter Name | Type | Description/Notes | +|----------------|--------|---------------------------------------------------------------------------------------| +| status | string | The status of the submitted `TokenUnfreezeTransaction` (from a `TransactionReceipt`). | + +### Additional Notes + +The tests contained in this specification will assume that a valid account and a valid token have already successfully created, associated, and frozen, unless otherwise specified. will denote the ID of the account, and will denote the private key of the created account as a DER-encoded hex string. will denote the ID of the created token, will denote the freeze key of the token as a DER-encoded hex string, and will denote the admin key of the token as a DER-encoded hex string. + +## Property Tests + +### **Token ID:** + +- The ID of the token to unfreeze. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|-----------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------|-------------------| +| 1 | Unfreezes a token on an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token unfreeze succeeds. | N | +| 2 | Unfreezes a token that doesn't exist on an account | tokenId="123.456.789", accountId= | The token unfreeze fails with an INVALID_TOKEN_ID response code from the network. | N | +| 3 | Unfreezes a token with an empty token ID on an account | tokenId="", accountId= | The token unfreeze fails with an SDK internal error. | N | +| 4 | Unfreezes a token with no token ID on an account | accountId= | The token unfreeze fails with an INVALID_TOKEN_ID response code from the network. | N | +| 5 | Unfreezes a deleted token on an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token unfreeze fails with an TOKEN_WAS_DELETED response code from the network. | N | +| 6 | Unfreezes a token on an account without signing with the token's freeze key | tokenId=, accountId= | The token unfreeze fails with an INVALID_SIGNATURE response code from the network. | N | +| 7 | Unfreezes a token but signs with the token's admin key | tokenId=, accountId=, commonTransactionParams.signers=[] | The token unfreeze fails with an INVALID_SIGNATURE response code from the network. | N | +| 8 | Unfreezes a token on an account but signs with an incorrect freeze key | tokenId=, accountId=, commonTransactionParams.signers=[] | The token unfreeze fails with an INVALID_SIGNATURE response code from the network. | N | +| 9 | Unfreezes a token with no freeze key on an account | tokenId=, accountId= | The token unfreeze fails with an TOKEN_HAS_NO_FREEZE_KEY response code from the network. | N | +| 10 | Unfreezes a token that is already unfrozen on an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token unfreeze succeeds. | N | +| 11 | Unfreezes a token on an account that is not associated with the token | tokenId=, accountId=, commonTransactionParams.signers=[] | The token unfreeze fails with an TOKEN_NOT_ASSOCIATED_WITH_ACCOUNT response code from the network. | N | +| 12 | Unfreezes a paused token on an account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token unfreeze fails with an TOKEN_IS_PAUSED response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "method": "unfreezeToken", + "params": { + "tokenId": "0.0.15432", + "accountId": "0.0.54811", + "commonTransactionParams": { + "signers": [ + "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "result": { + "status": "SUCCESS" + } +} +``` + +### **Account ID:** + +- The ID of the account to freeze. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|----------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|-------------------| +| 1 | Unfreezes a token on an account that doesn't exist | tokenId=, accountId="123.456.789", commonTransactionParams.signers=[] | The token freeze fails with an INVALID_ACCOUNT_ID response code from the network. | N | +| 2 | Unfreezes a token on an account with an empty account ID | tokenId=, accountId="", commonTransactionParams.signers=[] | The token freeze fails with an SDK internal error. | N | +| 3 | Unfreezes a token on an account with no account ID | tokenId=, commonTransactionParams.signers=[] | The token freeze fails with an INVALID_ACCOUNT_ID response code from the network. | N | +| 4 | Unfreezes a token on a deleted account | tokenId=, accountId=, commonTransactionParams.signers=[] | The token freeze fails with an ACCOUNT_WAS_DELETED response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "method": "unfreezeToken", + "params": { + "tokenId": "0.0.15432", + "accountId": "0.0.54811", + "commonTransactionParams": { + "signers": [ + "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "result": { + "status": "SUCCESS" + } +} +``` From bfd5f535b77b0567a67d63d4f15368e4c40650b7 Mon Sep 17 00:00:00 2001 From: ivaylogarnev Date: Thu, 5 Dec 2024 11:06:45 +0200 Subject: [PATCH 11/12] `feat(TCK-TS):` Migrate TCK to TypeScript for Improved Maintainability (#294) Signed-off-by: ivaylogarnev-limechain --- eslint.config.js => .eslintrc.cjs | 2 + .prettierrc | 12 + .prettierrc.js | 11 - README.md | 2 +- .../CommonTransactionParameters.md | 0 .../test-specifications/DevelopmentProcess.md | 26 +- .../test-specifications/ErrorCodes.md | 0 .../TestSpecificationsTemplate.md | 0 .../test-specifications/Utility.md | 0 .../crypto-service/AccountBalanceQuery.md | 0 .../AccountCreateTransaction.md | 0 .../AccountDeleteTransaction.md | 0 .../AccountUpdateTransaction.md | 0 .../token-service/CustomFee.md | 0 .../TokenAssociateTransaction.md | 0 .../token-service/TokenCreateTransaction.md | 0 .../token-service/TokenDeleteTransaction.md | 0 .../TokenDisscoiateTransaction.md | 0 .../TokenFeeScheduleUpdateTransaction.md | 0 .../token-service/TokenGrantKycTransaction.md | 0 .../token-service/TokenPauseTransaction.md | 0 .../TokenRevokeKycTransaction.md | 0 .../token-service/TokenUnpauseTransaction.md | 0 .../token-service/TokenUpdateTransaction.md | 0 .../token-service/tokenFreezeTransaction.md | 0 .../token-service/tokenUnfreezeTransaction.md | 0 mirrorNodeClient.js | 49 - package-lock.json | 1099 +++++++++++++++-- package.json | 17 +- client.js => src/services/Client.ts | 45 +- .../services/ConsensusInfoClient.ts | 31 +- src/services/MirrorNodeClient.ts | 30 + .../test-account-create-transaction.ts | 312 ++--- .../test-account-delete-transaction.ts | 75 +- .../test-account-update-transaction.ts | 282 ++--- .../test-token-create-transaction.ts | 901 +++++++------- .../test-token-delete-transaction.ts | 51 +- .../test-token-update-transaction.ts | 571 ++++----- .../utils/helpers/asn1-decoder.ts | 127 +- .../utils/helpers/constants/key-list.ts | 0 .../utils/helpers/constants/key-type.ts | 0 src/utils/helpers/custom-fees.ts | 283 +++++ src/utils/helpers/fetch-data.ts | 9 + .../key.js => src/utils/helpers/key.ts | 35 +- .../utils/helpers/retry-on-error.ts | 11 +- .../utils/helpers/setup-tests.ts | 12 +- .../token.js => src/utils/helpers/token.ts | 16 +- .../utils/helpers/verify-token-tx.ts | 70 +- tsconfig.json | 21 + utils/helpers/custom-fees.js | 275 ----- 50 files changed, 2686 insertions(+), 1689 deletions(-) rename eslint.config.js => .eslintrc.cjs (85%) create mode 100644 .prettierrc delete mode 100644 .prettierrc.js rename test-specifications/commonTransactionParameters.md => docs/test-specifications/CommonTransactionParameters.md (100%) rename DevelopmentProcess.md => docs/test-specifications/DevelopmentProcess.md (85%) rename test-specifications/errorCodes.md => docs/test-specifications/ErrorCodes.md (100%) rename test-specifications/testSpecificationsTemplate.md => docs/test-specifications/TestSpecificationsTemplate.md (100%) rename test-specifications/utility.md => docs/test-specifications/Utility.md (100%) rename test-specifications/crypto-service/accountBalanceQuery.md => docs/test-specifications/crypto-service/AccountBalanceQuery.md (100%) rename test-specifications/crypto-service/accountCreateTransaction.md => docs/test-specifications/crypto-service/AccountCreateTransaction.md (100%) rename test-specifications/crypto-service/accountDeleteTransaction.md => docs/test-specifications/crypto-service/AccountDeleteTransaction.md (100%) rename test-specifications/crypto-service/accountUpdateTransaction.md => docs/test-specifications/crypto-service/AccountUpdateTransaction.md (100%) rename test-specifications/token-service/customFee.md => docs/test-specifications/token-service/CustomFee.md (100%) rename test-specifications/token-service/tokenAssociateTransaction.md => docs/test-specifications/token-service/TokenAssociateTransaction.md (100%) rename test-specifications/token-service/tokenCreateTransaction.md => docs/test-specifications/token-service/TokenCreateTransaction.md (100%) rename test-specifications/token-service/tokenDeleteTransaction.md => docs/test-specifications/token-service/TokenDeleteTransaction.md (100%) rename test-specifications/token-service/tokenDisscoiateTransaction.md => docs/test-specifications/token-service/TokenDisscoiateTransaction.md (100%) rename test-specifications/token-service/tokenFeeScheduleUpdateTransaction.md => docs/test-specifications/token-service/TokenFeeScheduleUpdateTransaction.md (100%) rename test-specifications/token-service/tokenGrantKycTransaction.md => docs/test-specifications/token-service/TokenGrantKycTransaction.md (100%) rename test-specifications/token-service/tokenPauseTransaction.md => docs/test-specifications/token-service/TokenPauseTransaction.md (100%) rename test-specifications/token-service/tokenRevokeKycTransaction.md => docs/test-specifications/token-service/TokenRevokeKycTransaction.md (100%) rename test-specifications/token-service/tokenUnpauseTransaction.md => docs/test-specifications/token-service/TokenUnpauseTransaction.md (100%) rename test-specifications/token-service/tokenUpdateTransaction.md => docs/test-specifications/token-service/TokenUpdateTransaction.md (100%) rename {test-specifications => docs/test-specifications}/token-service/tokenFreezeTransaction.md (100%) rename {test-specifications => docs/test-specifications}/token-service/tokenUnfreezeTransaction.md (100%) delete mode 100644 mirrorNodeClient.js rename client.js => src/services/Client.ts (54%) rename consensusInfoClient.js => src/services/ConsensusInfoClient.ts (52%) create mode 100644 src/services/MirrorNodeClient.ts rename test/crypto-service/test_accountCreateTransaction.js => src/tests/crypto-service/test-account-create-transaction.ts (85%) rename test/crypto-service/test_accountDeleteTransaction.js => src/tests/crypto-service/test-account-delete-transaction.ts (85%) rename test/crypto-service/test_accountUpdateTransaction.js => src/tests/crypto-service/test-account-update-transaction.ts (85%) rename test/token-service/test_tokenCreateTransaction.js => src/tests/token-service/test-token-create-transaction.ts (90%) rename test/token-service/test_tokenDeleteTransaction.js => src/tests/token-service/test-token-delete-transaction.ts (82%) rename test/token-service/test_tokenUpdateTransaction.js => src/tests/token-service/test-token-update-transaction.ts (89%) rename utils/helpers/asn1-decoder.js => src/utils/helpers/asn1-decoder.ts (54%) rename utils/helpers/constants/key-list.js => src/utils/helpers/constants/key-list.ts (100%) rename utils/helpers/constants/key-type.js => src/utils/helpers/constants/key-type.ts (100%) create mode 100644 src/utils/helpers/custom-fees.ts create mode 100644 src/utils/helpers/fetch-data.ts rename utils/helpers/key.js => src/utils/helpers/key.ts (73%) rename utils/helpers/retry-on-error.js => src/utils/helpers/retry-on-error.ts (79%) rename setup_Tests.js => src/utils/helpers/setup-tests.ts (54%) rename utils/helpers/token.js => src/utils/helpers/token.ts (81%) rename utils/helpers/verify-token-tx.js => src/utils/helpers/verify-token-tx.ts (65%) create mode 100644 tsconfig.json delete mode 100644 utils/helpers/custom-fees.js diff --git a/eslint.config.js b/.eslintrc.cjs similarity index 85% rename from eslint.config.js rename to .eslintrc.cjs index f2c79b7..d97fd19 100644 --- a/eslint.config.js +++ b/.eslintrc.cjs @@ -7,6 +7,7 @@ export default defineConfig([ console: "readonly", }, }, + extends: ["plugin:prettier/recommended"], rules: { "no-console": ["warn", { allow: ["warn"] }], "prefer-const": "error", @@ -15,6 +16,7 @@ export default defineConfig([ eqeqeq: ["error", "always"], "no-multi-spaces": ["error"], "no-duplicate-imports": ["error"], + "prettier/prettier": "error", }, ignores: ["mochawesome-report/**"], }, diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..07a2cea --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": false, + "trailingComma": "all", + "bracketSpacing": true, + "arrowParens": "always", + "endOfLine": "lf" +} + diff --git a/.prettierrc.js b/.prettierrc.js deleted file mode 100644 index a00d427..0000000 --- a/.prettierrc.js +++ /dev/null @@ -1,11 +0,0 @@ -export default { - printWidth: 80, - tabWidth: 2, - useTabs: false, - semi: true, - singleQuote: false, - trailingComma: "all", - bracketSpacing: true, - arrowParens: "always", - endOfLine: "lf", -}; diff --git a/README.md b/README.md index f7d1dc1..693f8e5 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ npm install Run specific test file ``` -npm run test test/account/test_accountCreateTransaction.js +npm run test src/tests/account-service/test-account-create-transaction.js ``` Run all tests diff --git a/test-specifications/commonTransactionParameters.md b/docs/test-specifications/CommonTransactionParameters.md similarity index 100% rename from test-specifications/commonTransactionParameters.md rename to docs/test-specifications/CommonTransactionParameters.md diff --git a/DevelopmentProcess.md b/docs/test-specifications/DevelopmentProcess.md similarity index 85% rename from DevelopmentProcess.md rename to docs/test-specifications/DevelopmentProcess.md index 684eedd..1c266f4 100644 --- a/DevelopmentProcess.md +++ b/docs/test-specifications/DevelopmentProcess.md @@ -8,8 +8,8 @@ Since the process outlined will require coordination across all SDKs, having a d | SDK | Lead | Github handle | |-----------------------|-------------------|--------------------| -| Javascript/Typescript | Svetoslav Nikolov | @svetoslav-nikol0v | -| Java | Nikita Lebedev | @thenswan | +| Javascript/Typescript | Ivaylo Nikolov | @ivaylonikolov7 | +| Java | Nikola Naydenov | @naydenovn | | Go | Ivan Ivanov | @0xivanov | | C++ | Rob Walworth | @rwalworth | | Swift | Ricky Saechao | @RickyLB | @@ -21,9 +21,9 @@ The TCK development process encompasses all work done for a Hedera request type, ### Step 1: Documentation -Before any development takes place, the tests to be written need to be thought out and put in a markdown file in the `test-specifications` folder. A new file should use the `test-specifications/testSpecificationsTemplate.md` file as a template. The new markdown file should also be placed within a folder within the `test-specifications` folder that contains all the tests for the particular Hedera service that services the request for which tests are being written. For example, if tests are being written for `AccountCreateTransaction`, the `accountCreateTransaction.md` file should be placed in `test-specifications/crypto-service`. +Before any development takes place, the tests to be written need to be thought out and put in a markdown file in the `test-specifications` folder inside the `docs` directory. A new file should use the `test-specifications/TestSpecificationsTemplate.md` file as a template. The new markdown file should also be placed within a folder within the `test-specifications` folder that contains all the tests for the particular Hedera service that services the request for which tests are being written. For example, if tests are being written for `AccountCreateTransaction`, the `AccountCreateTransaction.md` file should be placed in `test-specifications/crypto-service`. -The items that should be included in a request's test documentation can be seen by looking at the `testSpecificationsTemplate.md` file. These items include: +The items that should be included in a request's test documentation can be seen by looking at the `TestSpecificationsTemplate.md` file. These items include: - Description: A description of the test specification. This, for the most part, should be copy-paste between test files with slight changes for names, links, etc. - Design: A brief rundown of what is being tested, how it's being tested, and how the test results can be verified. - Request properties: A link to the Hedera documentation for the request. @@ -49,21 +49,21 @@ Once the tests have been written, they can be put up for in a pull request. The ### Step 2a: TCK Test Driver -Once the tests are written, approved, and merged, they can then be developed. The approved and merged test documentation should be used to discern what tests to write and how they should operate. Much like the test documentation, the file that contains the code for the tests should be placed within a folder within the `test` folder that contains all the tests for the particular Hedera service that services the request for which the tests are being written. For example, if tests are being written for `AccountCreateTransaction`, the `test_accountCreateTransaction.js` file should be placed in `test/crypto-service`. +Once the tests are written, approved, and merged, they can then be developed. The approved and merged test documentation should be used to discern what tests to write and how they should operate. Much like the test documentation, the file that contains the code for the tests should be placed within a folder within the `tests` folder that contains all the tests for the particular Hiero service that services the request for which the tests are being written. For example, if tests are being written for `AccountCreateTransaction`, the `test-account-create-transaction.ts` file should be placed in `tests/crypto-service`. A few guidelines for developing the tests: - - The name of the test file should match the name of the documentation, with a `test_` prepended to the file name, and obviously the different file extension. So a documentation markdown file named `accountCreateTransaction.md` would have its test implementation file named `test_accountCreateTransaction.js`. + - The name of the test file should be `kebap-case` and match the name of the documentation, with a `test-` prepended to the file name, and obviously the different file extension. So a documentation markdown file named `AccountCreateTransaction.md` would have its test implementation file named `test-account-create-transaction.ts`. - A `describe` call should be used to wrap all the tests for a request type, and it should be described with the name of the request being tested. ```jsx -describe("AccountCreateTransaction", function () { +describe("AccountCreateTransaction", () => { //... }); ``` - Another `describe` call should wrap all tests associated with one property/function for the request type and be named the property/function name. ```jsx -describe("AccountCreateTransaction", function () { +describe("AccountCreateTransaction", () => { //... - describe("Key", function () { + describe("Key", () => { //... }); //... @@ -71,14 +71,14 @@ describe("AccountCreateTransaction", function () { ``` - Finally, an `it` call should wrap each test and should use the same name as described in the test documentation, as well as prepended with the test number in parentheses. ```jsx -describe("AccountCreateTransaction", function () { +describe("AccountCreateTransaction", () => { //... - describe("Key", function () { + describe("Key", () => { //... - it("(#1) Creates an account with a valid key", async function () { + it("(#1) Creates an account with a valid key", async () => { //... }); - it("(#2) Creates an account with no key", async function () { + it("(#2) Creates an account with no key", async () => { //... }); //... diff --git a/test-specifications/errorCodes.md b/docs/test-specifications/ErrorCodes.md similarity index 100% rename from test-specifications/errorCodes.md rename to docs/test-specifications/ErrorCodes.md diff --git a/test-specifications/testSpecificationsTemplate.md b/docs/test-specifications/TestSpecificationsTemplate.md similarity index 100% rename from test-specifications/testSpecificationsTemplate.md rename to docs/test-specifications/TestSpecificationsTemplate.md diff --git a/test-specifications/utility.md b/docs/test-specifications/Utility.md similarity index 100% rename from test-specifications/utility.md rename to docs/test-specifications/Utility.md diff --git a/test-specifications/crypto-service/accountBalanceQuery.md b/docs/test-specifications/crypto-service/AccountBalanceQuery.md similarity index 100% rename from test-specifications/crypto-service/accountBalanceQuery.md rename to docs/test-specifications/crypto-service/AccountBalanceQuery.md diff --git a/test-specifications/crypto-service/accountCreateTransaction.md b/docs/test-specifications/crypto-service/AccountCreateTransaction.md similarity index 100% rename from test-specifications/crypto-service/accountCreateTransaction.md rename to docs/test-specifications/crypto-service/AccountCreateTransaction.md diff --git a/test-specifications/crypto-service/accountDeleteTransaction.md b/docs/test-specifications/crypto-service/AccountDeleteTransaction.md similarity index 100% rename from test-specifications/crypto-service/accountDeleteTransaction.md rename to docs/test-specifications/crypto-service/AccountDeleteTransaction.md diff --git a/test-specifications/crypto-service/accountUpdateTransaction.md b/docs/test-specifications/crypto-service/AccountUpdateTransaction.md similarity index 100% rename from test-specifications/crypto-service/accountUpdateTransaction.md rename to docs/test-specifications/crypto-service/AccountUpdateTransaction.md diff --git a/test-specifications/token-service/customFee.md b/docs/test-specifications/token-service/CustomFee.md similarity index 100% rename from test-specifications/token-service/customFee.md rename to docs/test-specifications/token-service/CustomFee.md diff --git a/test-specifications/token-service/tokenAssociateTransaction.md b/docs/test-specifications/token-service/TokenAssociateTransaction.md similarity index 100% rename from test-specifications/token-service/tokenAssociateTransaction.md rename to docs/test-specifications/token-service/TokenAssociateTransaction.md diff --git a/test-specifications/token-service/tokenCreateTransaction.md b/docs/test-specifications/token-service/TokenCreateTransaction.md similarity index 100% rename from test-specifications/token-service/tokenCreateTransaction.md rename to docs/test-specifications/token-service/TokenCreateTransaction.md diff --git a/test-specifications/token-service/tokenDeleteTransaction.md b/docs/test-specifications/token-service/TokenDeleteTransaction.md similarity index 100% rename from test-specifications/token-service/tokenDeleteTransaction.md rename to docs/test-specifications/token-service/TokenDeleteTransaction.md diff --git a/test-specifications/token-service/tokenDisscoiateTransaction.md b/docs/test-specifications/token-service/TokenDisscoiateTransaction.md similarity index 100% rename from test-specifications/token-service/tokenDisscoiateTransaction.md rename to docs/test-specifications/token-service/TokenDisscoiateTransaction.md diff --git a/test-specifications/token-service/tokenFeeScheduleUpdateTransaction.md b/docs/test-specifications/token-service/TokenFeeScheduleUpdateTransaction.md similarity index 100% rename from test-specifications/token-service/tokenFeeScheduleUpdateTransaction.md rename to docs/test-specifications/token-service/TokenFeeScheduleUpdateTransaction.md diff --git a/test-specifications/token-service/tokenGrantKycTransaction.md b/docs/test-specifications/token-service/TokenGrantKycTransaction.md similarity index 100% rename from test-specifications/token-service/tokenGrantKycTransaction.md rename to docs/test-specifications/token-service/TokenGrantKycTransaction.md diff --git a/test-specifications/token-service/tokenPauseTransaction.md b/docs/test-specifications/token-service/TokenPauseTransaction.md similarity index 100% rename from test-specifications/token-service/tokenPauseTransaction.md rename to docs/test-specifications/token-service/TokenPauseTransaction.md diff --git a/test-specifications/token-service/tokenRevokeKycTransaction.md b/docs/test-specifications/token-service/TokenRevokeKycTransaction.md similarity index 100% rename from test-specifications/token-service/tokenRevokeKycTransaction.md rename to docs/test-specifications/token-service/TokenRevokeKycTransaction.md diff --git a/test-specifications/token-service/tokenUnpauseTransaction.md b/docs/test-specifications/token-service/TokenUnpauseTransaction.md similarity index 100% rename from test-specifications/token-service/tokenUnpauseTransaction.md rename to docs/test-specifications/token-service/TokenUnpauseTransaction.md diff --git a/test-specifications/token-service/tokenUpdateTransaction.md b/docs/test-specifications/token-service/TokenUpdateTransaction.md similarity index 100% rename from test-specifications/token-service/tokenUpdateTransaction.md rename to docs/test-specifications/token-service/TokenUpdateTransaction.md diff --git a/test-specifications/token-service/tokenFreezeTransaction.md b/docs/test-specifications/token-service/tokenFreezeTransaction.md similarity index 100% rename from test-specifications/token-service/tokenFreezeTransaction.md rename to docs/test-specifications/token-service/tokenFreezeTransaction.md diff --git a/test-specifications/token-service/tokenUnfreezeTransaction.md b/docs/test-specifications/token-service/tokenUnfreezeTransaction.md similarity index 100% rename from test-specifications/token-service/tokenUnfreezeTransaction.md rename to docs/test-specifications/token-service/tokenUnfreezeTransaction.md diff --git a/mirrorNodeClient.js b/mirrorNodeClient.js deleted file mode 100644 index f0f8767..0000000 --- a/mirrorNodeClient.js +++ /dev/null @@ -1,49 +0,0 @@ -import axios from "axios"; - -class MirrorNodeClient { - constructor() { - this.mirrorNodeRestUrl = process.env.MIRROR_NODE_REST_URL; - this.NODE_TIMEOUT = process.env.NODE_TIMEOUT; - } - - async getAccountData(accountId) { - const url = `${this.mirrorNodeRestUrl}/api/v1/accounts/${accountId}`; - return this.retryUntilData(url); - } - - async getBalanceData() { - const url = `${this.mirrorNodeRestUrl}/api/v1/balances`; - return this.retryUntilData(url); - } - - async getTokenData(tokenId) { - const url = `${this.mirrorNodeRestUrl}/api/v1/tokens/${tokenId}`; - return this.retryUntilData(url); - } - - async retryUntilData(url) { - const maxRetries = Math.floor(this.NODE_TIMEOUT / 1000); // retry once per second - let retries = 0; - - while (retries < maxRetries) { - try { - const response = await axios.get(url); - - if (response.data) { - return response.data; - } - } catch (error) { - // Uncomment if you want to see the error - // console.error(error); - } - - // If the array is empty, delay for a second before the next try - await new Promise((resolve) => setTimeout(resolve, 1000)); - retries++; - } - - throw new Error("Max retries reached without data"); - } -} - -export default new MirrorNodeClient(); diff --git a/package-lock.json b/package-lock.json index d5618fa..b7ad83e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,12 +13,35 @@ "mocha": "^9.2.2" }, "devDependencies": { - "eslint": "^9.11.1", + "@types/chai": "^5.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.9.1", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", + "eslint": "^9.15.0", "eslint-config-prettier": "^9.1.0", "eslint-define-config": "^2.1.0", "eslint-plugin-prettier": "^5.2.1", "mochawesome": "^7.1.3", - "prettier": "^3.3.3" + "mochawesome-merge": "^4.3.0", + "mochawesome-report-generator": "^6.2.0", + "prettier": "^3.3.3", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.6.3" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" } }, "node_modules/@eslint-community/eslint-utils": { @@ -49,19 +72,21 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", + "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.4", "debug": "^4.3.1", @@ -76,6 +101,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -84,19 +110,21 @@ } }, "node_modules/@eslint/core": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", - "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", + "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -120,6 +148,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -128,10 +157,11 @@ } }, "node_modules/@eslint/js": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz", - "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", + "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -141,15 +171,17 @@ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "levn": "^0.4.1" }, @@ -684,6 +716,44 @@ } } }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -698,10 +768,11 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -710,11 +781,40 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -728,6 +828,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -737,6 +838,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -750,6 +852,7 @@ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, @@ -811,6 +914,51 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.0.1.tgz", + "integrity": "sha512-5T8ajsg3M/FOncpLYW7sdOcD6yf4+722sze/tc4KQV0P8Z2rAr3SAuHCIkYmYpt8VbcQlnz8SxlOlPQYefe4cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -828,10 +976,299 @@ "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, + "node_modules/@types/mocha": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { - "version": "20.4.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.5.tgz", - "integrity": "sha512-rt40Nk13II9JwQBdeYqmbn2Q6IVTA5uPhvSO+JVqdXw/6/4glI6oR9ezty/A9Hg5u7JH4OmYmuQ+XvjKm0Datg==" + "version": "22.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.1.tgz", + "integrity": "sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", @@ -850,10 +1287,11 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -866,15 +1304,30 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -928,6 +1381,13 @@ "node": ">= 8" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1081,6 +1541,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1220,11 +1681,19 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1378,31 +1847,32 @@ } }, "node_modules/eslint": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz", - "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.15.0.tgz", + "integrity": "sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.6.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.11.1", - "@eslint/plugin-kit": "^0.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.15.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", + "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.5", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.2", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -1412,14 +1882,11 @@ "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -1444,6 +1911,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -1477,6 +1945,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.9.1" @@ -1503,10 +1972,11 @@ } }, "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -1519,10 +1989,11 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -1555,14 +2026,15 @@ } }, "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1588,6 +2060,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -1638,19 +2111,39 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -1676,6 +2169,7 @@ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -1777,6 +2271,21 @@ "node": ">= 6" } }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1863,6 +2372,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -1876,6 +2386,13 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -2011,6 +2528,7 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2084,20 +2602,11 @@ } }, "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "engines": { - "node": ">=8" + "node": ">=0.12.0" } }, "node_modules/is-plain-obj": { @@ -2174,7 +2683,8 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -2188,6 +2698,29 @@ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -2299,6 +2832,37 @@ "get-func-name": "^2.0.0" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -2394,6 +2958,7 @@ "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-7.1.3.tgz", "integrity": "sha512-Vkb3jR5GZ1cXohMQQ73H3cZz7RoxGjjUo0G5hu0jLaW+0FdUxUwg3Cj29bqQdh0rFcnyV06pWmqmi5eBPnEuNQ==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.2", "diff": "^5.0.0", @@ -2410,11 +2975,177 @@ "mocha": ">=7" } }, + "node_modules/mochawesome-merge": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mochawesome-merge/-/mochawesome-merge-4.3.0.tgz", + "integrity": "sha512-1roR6g+VUlfdaRmL8dCiVpKiaUhbPVm1ZQYUM6zHX46mWk+tpsKVZR6ba98k2zc8nlPvYd71yn5gyH970pKBSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-extra": "^7.0.1", + "glob": "^7.1.6", + "yargs": "^15.3.1" + }, + "bin": { + "mochawesome-merge": "bin/mochawesome-merge.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mochawesome-merge/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mochawesome-merge/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/mochawesome-merge/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mochawesome-merge/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mochawesome-merge/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/mochawesome-merge/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/mochawesome-report-generator": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-6.2.0.tgz", "integrity": "sha512-Ghw8JhQFizF0Vjbtp9B0i//+BOkV5OWcQCPpbO0NGOoxV33o+gKDYU0Pr2pGxkIHnqZ+g5mYiXF7GMNgAcDpSg==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.2", "dateformat": "^4.5.1", @@ -2632,11 +3363,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -2665,6 +3407,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2761,6 +3504,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -2776,6 +3520,7 @@ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, + "license": "MIT", "dependencies": { "fast-diff": "^1.1.2" }, @@ -2860,6 +3605,7 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -2898,7 +3644,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/quick-format-unescaped": { "version": "4.0.4", @@ -2955,11 +3702,19 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true, + "license": "ISC" + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -2969,6 +3724,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -2999,6 +3755,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -3035,6 +3792,19 @@ "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", @@ -3043,11 +3813,19 @@ "randombytes": "^2.1.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -3060,6 +3838,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3117,6 +3896,16 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3143,10 +3932,11 @@ } }, "node_modules/synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, + "license": "MIT", "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" @@ -3173,12 +3963,6 @@ "tcomb": "^3.0.0" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "node_modules/thread-stream": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.3.0.tgz", @@ -3198,6 +3982,88 @@ "node": ">=8.0" } }, + "node_modules/ts-api-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tslib": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", @@ -3229,11 +4095,42 @@ "node": ">=4" } }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -3248,6 +4145,13 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, "node_modules/validator": { "version": "13.7.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", @@ -3271,6 +4175,13 @@ "node": ">= 8" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true, + "license": "ISC" + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -3353,6 +4264,16 @@ "node": ">=10" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index aaae864..f9dcee2 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,4 @@ { - "type": "module", "dependencies": { "@hashgraph/sdk": "^v2.51.0", "axios": "^1.6.0", @@ -9,16 +8,26 @@ "mocha": "^9.2.2" }, "scripts": { - "test": "mocha --recursive --reporter mochawesome --exit", + "test": "mocha --require ts-node/register --require tsconfig-paths/register --recursive 'src/tests/**/*.ts' --reporter mochawesome", "format": "prettier --write .", "lint": "eslint ." }, "devDependencies": { - "eslint": "^9.11.1", + "@types/chai": "^5.0.1", + "@types/mocha": "^10.0.10", + "@types/node": "^22.9.1", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", + "eslint": "^9.15.0", "eslint-config-prettier": "^9.1.0", "eslint-define-config": "^2.1.0", "eslint-plugin-prettier": "^5.2.1", "mochawesome": "^7.1.3", - "prettier": "^3.3.3" + "mochawesome-merge": "^4.3.0", + "mochawesome-report-generator": "^6.2.0", + "prettier": "^3.3.3", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.6.3" } } diff --git a/client.js b/src/services/Client.ts similarity index 54% rename from client.js rename to src/services/Client.ts index d6e2d29..1420791 100644 --- a/client.js +++ b/src/services/Client.ts @@ -1,31 +1,38 @@ -import { JSONRPC, JSONRPCClient } from "json-rpc-2.0"; +import { JSONRPC, JSONRPCClient, CreateID } from "json-rpc-2.0"; import axios from "axios"; import "dotenv/config"; let nextID = 0; -const createID = () => nextID++; +const createID: CreateID = () => nextID++; // JSONRPCClient needs to know how to send a JSON-RPC request. // Tell it by passing a function to its constructor. The function must take a JSON-RPC request and send it. -const JSONRPClient = new JSONRPCClient(async (jsonRPCRequest) => { - try { - const response = await axios.post("http://localhost", jsonRPCRequest, { - headers: { - "Content-Type": "application/json", - }, - }); +const JSONRPClient = new JSONRPCClient( + async (jsonRPCRequest): Promise => { + try { + const response = await axios.post("http://localhost", jsonRPCRequest, { + headers: { + "Content-Type": "application/json", + }, + }); - if (response.status === 200) { - return JSONRPClient.receive(response.data); - } else if (jsonRPCRequest.id !== undefined) { - throw new Error(response.statusText); + if (response.status === 200) { + return JSONRPClient.receive(response.data); + } else if (jsonRPCRequest.id !== undefined) { + throw new Error(response.statusText); + } + } catch (error) { + throw error; } - } catch (error) { - throw error; - } -}, createID()); + }, + createID, +); -export async function JSONRPCRequest(mochaTestContext, method, params) { +export const JSONRPCRequest = async ( + mochaTestContext: any, + method: string, + params?: any, +) => { const jsonRPCRequest = { jsonrpc: JSONRPC, id: createID(), @@ -51,4 +58,4 @@ export async function JSONRPCRequest(mochaTestContext, method, params) { } return jsonRPCResponse.result; } -} +}; diff --git a/consensusInfoClient.js b/src/services/ConsensusInfoClient.ts similarity index 52% rename from consensusInfoClient.js rename to src/services/ConsensusInfoClient.ts index 2d5cdf0..25e65b1 100644 --- a/consensusInfoClient.js +++ b/src/services/ConsensusInfoClient.ts @@ -1,12 +1,16 @@ import { + AccountBalance, AccountBalanceQuery, AccountId, + AccountInfo, AccountInfoQuery, Client, + TokenInfo, TokenInfoQuery, } from "@hashgraph/sdk"; class ConsensusInfoClient { + sdkClient; constructor() { if ( process.env.NODE_IP && @@ -24,29 +28,38 @@ class ConsensusInfoClient { } this.sdkClient.setOperator( - process.env.OPERATOR_ACCOUNT_ID, - process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + process.env.OPERATOR_ACCOUNT_ID as string, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY as string, ); } - async getBalance(accountId) { - return this.executeAccountMethod(accountId, new AccountBalanceQuery()); + async getBalance(accountId: string): Promise { + return this.executeAccountMethod( + accountId, + new AccountBalanceQuery(), + ) as Promise; } - async getAccountInfo(accountId) { - return this.executeAccountMethod(accountId, new AccountInfoQuery()); + async getAccountInfo(accountId: string): Promise { + return this.executeAccountMethod( + accountId, + new AccountInfoQuery(), + ) as Promise; } - async getTokenInfo(tokenId) { + async getTokenInfo(tokenId: string): Promise { return this.executeTokenMethod(tokenId, new TokenInfoQuery()); } - async executeAccountMethod(accountId, method) { + async executeAccountMethod( + accountId: string, + method: AccountInfoQuery | AccountBalanceQuery, + ) { method.setAccountId(accountId); return method.execute(this.sdkClient); } - async executeTokenMethod(tokenId, method) { + async executeTokenMethod(tokenId: string, method: TokenInfoQuery) { method.setTokenId(tokenId); return method.execute(this.sdkClient); } diff --git a/src/services/MirrorNodeClient.ts b/src/services/MirrorNodeClient.ts new file mode 100644 index 0000000..75e459e --- /dev/null +++ b/src/services/MirrorNodeClient.ts @@ -0,0 +1,30 @@ +import { fetchData } from "../utils/helpers/fetch-data"; +import { retryOnError } from "../utils/helpers/retry-on-error"; + +class MirrorNodeClient { + private mirrorNodeRestUrl: string | undefined; + + constructor() { + this.mirrorNodeRestUrl = process.env.MIRROR_NODE_REST_URL; + } + + // TODO: Get mirror node interface with OpenAPI + async getAccountData(accountId: string): Promise { + const url = `${this.mirrorNodeRestUrl}/api/v1/accounts/${accountId}`; + return retryOnError(async () => fetchData(url)); + } + + // TODO: Get mirror node interface with OpenAPI + async getBalanceData(): Promise { + const url = `${this.mirrorNodeRestUrl}/api/v1/balances`; + return retryOnError(async () => fetchData(url)); + } + + // TODO: Get mirror node interface with OpenAPI + async getTokenData(tokenId: string): Promise { + const url = `${this.mirrorNodeRestUrl}/api/v1/tokens/${tokenId}`; + return retryOnError(async () => fetchData(url)); + } +} + +export default new MirrorNodeClient(); diff --git a/test/crypto-service/test_accountCreateTransaction.js b/src/tests/crypto-service/test-account-create-transaction.ts similarity index 85% rename from test/crypto-service/test_accountCreateTransaction.js rename to src/tests/crypto-service/test-account-create-transaction.ts index 68a4c17..1b582b0 100644 --- a/test/crypto-service/test_accountCreateTransaction.js +++ b/src/tests/crypto-service/test-account-create-transaction.ts @@ -1,15 +1,15 @@ import crypto from "crypto"; import { assert, expect } from "chai"; -import { JSONRPCRequest } from "../../client.js"; -import mirrorNodeClient from "../../mirrorNodeClient.js"; -import consensusInfoClient from "../../consensusInfoClient.js"; -import { setOperator } from "../../setup_Tests.js"; +import { JSONRPCRequest } from "@services/Client"; +import mirrorNodeClient from "@services/MirrorNodeClient"; +import consensusInfoClient from "@services/ConsensusInfoClient"; +import { setOperator } from "@helpers/setup-tests"; import { - twoLevelsNestedKeyListParams, fourKeysKeyListParams, -} from "../../utils/helpers/constants/key-list.js"; + twoLevelsNestedKeyListParams, +} from "@helpers/constants/key-list"; /** * Tests for AccountCreateTransaction @@ -19,33 +19,35 @@ describe("AccountCreateTransaction", function () { // Tests should not take longer than 30 seconds to fully execute. this.timeout(30000); - beforeEach(async function () { + beforeEach(async () => { await setOperator( - process.env.OPERATOR_ACCOUNT_ID, - process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + this, + process.env.OPERATOR_ACCOUNT_ID as string, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY as string, ); }); - afterEach(async function () { + afterEach(async () => { await JSONRPCRequest(this, "reset"); }); - describe("Key", function () { - async function verifyOnlyAccountCreation(accountId) { + describe("Key", () => { + const verifyOnlyAccountCreation = async (accountId: string) => { // If the account was created successfully, the queried account's IDs should be equal. expect(accountId).to.equal( - await ( + ( await consensusInfoClient.getAccountInfo(accountId) ).accountId.toString(), ); + expect(accountId).to.equal( await ( await mirrorNodeClient.getAccountData(accountId) ).account, ); - } + }; - it("(#1) Creates an account with a valid ED25519 public key", async function () { + it("(#1) Creates an account with a valid ED25519 public key", async () => { // Generate an ED25519 public key for the account. const ed25519PublicKey = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", @@ -60,12 +62,12 @@ describe("AccountCreateTransaction", function () { await verifyOnlyAccountCreation(response.accountId); }); - it("(#2) Creates an account with a valid ECDSAsecp256k1 public key", async function () { + it("(#2) Creates an account with a valid ECDSAsecp256k1 public key", async () => { // Generate an ECDSAsecp256k1 public key for the account. //prettier-ignore const ecdsaSecp256k1PublicKey = await JSONRPCRequest(this, "generateKey", { - type: "ecdsaSecp256k1PublicKey", - }); + type: "ecdsaSecp256k1PublicKey", + }); // Attempt to create an account. const response = await JSONRPCRequest(this, "createAccount", { @@ -76,7 +78,7 @@ describe("AccountCreateTransaction", function () { await verifyOnlyAccountCreation(response.accountId); }); - it("(#3) Creates an account with a valid ED25519 private key", async function () { + it("(#3) Creates an account with a valid ED25519 private key", async () => { // Generate an ED25519 private key for the account. const ed25519PrivateKey = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -91,12 +93,12 @@ describe("AccountCreateTransaction", function () { await verifyOnlyAccountCreation(response.accountId); }); - it("(#4) Creates an account with a valid ECDSAsecp256k1 private key", async function () { + it("(#4) Creates an account with a valid ECDSAsecp256k1 private key", async () => { // Generate an ECDSAsecp256k1 private key for the account. //prettier-ignore const ecdsaSecp256k1PrivateKey = await JSONRPCRequest(this, "generateKey", { - type: "ecdsaSecp256k1PrivateKey", - }); + type: "ecdsaSecp256k1PrivateKey", + }); // Attempt to create an account. const response = await JSONRPCRequest(this, "createAccount", { @@ -107,7 +109,7 @@ describe("AccountCreateTransaction", function () { await verifyOnlyAccountCreation(response.accountId); }); - it("(#5) Creates an account with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys", async function () { + it("(#5) Creates an account with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys", async () => { // Generate a KeyList of ED25519 and ECDSAsecp256k1 private and public keys for the account. const keyList = await JSONRPCRequest( this, @@ -124,7 +126,7 @@ describe("AccountCreateTransaction", function () { await verifyOnlyAccountCreation(response.accountId); }); - it("(#6) Creates an account with a valid KeyList of nested Keylists (three levels)", async function () { + it("(#6) Creates an account with a valid KeyList of nested Keylists (three levels)", async () => { // Generate a KeyList of nested KeyLists of ED25519 and ECDSAsecp256k1 private and public keys for the account. const nestedKeyList = await JSONRPCRequest( this, @@ -141,11 +143,11 @@ describe("AccountCreateTransaction", function () { await verifyOnlyAccountCreation(response.accountId); }); - it("(#7) Creates an account with no key", async function () { + it("(#7) Creates an account with no key", async () => { try { // Attempt to create an account without providing a key. The network should respond with a KEY_REQUIRED status. await JSONRPCRequest(this, "createAccount", {}); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "KEY_REQUIRED"); return; } @@ -154,13 +156,13 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#8) Creates an account with an invalid key", async function () { + it("(#8) Creates an account with an invalid key", async () => { try { // Attempt to create an account with an invalid key (random 88 bytes, which is equal to the byte length of a valid public key). The SDK should throw an internal error. await JSONRPCRequest(this, "createAccount", { key: crypto.randomBytes(88).toString("hex"), }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -170,17 +172,16 @@ describe("AccountCreateTransaction", function () { }); }); - describe("Initial Balance", function () { - async function verifyAccountCreationWithInitialBalance( - accountId, - initialBalance, - ) { + describe("Initial Balance", () => { + const verifyAccountCreationWithInitialBalance = async ( + accountId: string, + initialBalance: number, + ) => { // If the account was created successfully, the queried account's balances should be equal. expect(initialBalance).to.equal( Number( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).balance._valueInTinybar, + (await consensusInfoClient.getAccountInfo(accountId)).balance + ._valueInTinybar, ), ); expect(initialBalance).to.equal( @@ -190,9 +191,9 @@ describe("AccountCreateTransaction", function () { ).balance.balance, ), ); - } + }; - it("(#1) Creates an account with an initial balance", async function () { + it("(#1) Creates an account with an initial balance", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -212,7 +213,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#2) Creates an account with no initial balance", async function () { + it("(#2) Creates an account with no initial balance", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", @@ -232,7 +233,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#3) Creates an account with a negative initial balance", async function () { + it("(#3) Creates an account with a negative initial balance", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", @@ -244,7 +245,7 @@ describe("AccountCreateTransaction", function () { key: key.key, initialBalance: -1, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_INITIAL_BALANCE"); return; } @@ -253,10 +254,10 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Creates an account with an initial balance higher than the operator account balance", async function () { + it("(#4) Creates an account with an initial balance higher than the operator account balance", async () => { // Get the operator account balance. const operatorBalanceData = await mirrorNodeClient.getAccountData( - process.env.OPERATOR_ACCOUNT_ID, + process.env.OPERATOR_ACCOUNT_ID as string, ); const operatorAccountBalance = Number( @@ -274,7 +275,7 @@ describe("AccountCreateTransaction", function () { key: key.key, initialBalance: operatorAccountBalance + 1, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INSUFFICIENT_PAYER_BALANCE"); return; } @@ -284,25 +285,24 @@ describe("AccountCreateTransaction", function () { }); }); - describe("Receiver Signature Required", function () { - async function verifyAccountCreationWithReceiverSignatureRequired( - accountId, - receiverSignatureRequired, - ) { + describe("Receiver Signature Required", () => { + const verifyAccountCreationWithReceiverSignatureRequired = async ( + accountId: string, + receiverSignatureRequired: boolean, + ) => { // If the account was created successfully, the queried account's receiver signature required policies should be equal. expect(receiverSignatureRequired).to.equal( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).isReceiverSignatureRequired, + (await consensusInfoClient.getAccountInfo(accountId)) + .isReceiverSignatureRequired, ); expect(receiverSignatureRequired).to.equal( await ( await mirrorNodeClient.getAccountData(accountId) ).receiver_sig_required, ); - } + }; - it("(#1) Creates an account that requires a receiving signature", async function () { + it("(#1) Creates an account that requires a receiving signature", async () => { // Generate a valid private key for the account. const privateKey = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -331,7 +331,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#2) Creates an account that doesn't require a receiving signature", async function () { + it("(#2) Creates an account that doesn't require a receiving signature", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", @@ -351,7 +351,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#3) Creates an account that requires a receiving signature but isn't signed by the account key", async function () { + it("(#3) Creates an account that requires a receiving signature but isn't signed by the account key", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", @@ -363,7 +363,7 @@ describe("AccountCreateTransaction", function () { key: key.key, receiverSignatureRequired: true, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -373,11 +373,11 @@ describe("AccountCreateTransaction", function () { }); }); - describe("Auto Renew Period", function () { - async function verifyAccountCreationWithAutoRenewPeriod( - accountId, - autoRenewPeriodSeconds, - ) { + describe("Auto Renew Period", () => { + const verifyAccountCreationWithAutoRenewPeriod = async ( + accountId: string, + autoRenewPeriodSeconds: number, + ) => { // If the account was created successfully, the queried account's auto renew periods should be equal. expect(autoRenewPeriodSeconds).to.equal( Number( @@ -391,9 +391,9 @@ describe("AccountCreateTransaction", function () { await mirrorNodeClient.getAccountData(accountId) ).auto_renew_period, ); - } + }; - it("(#1) Creates an account with an auto renew period set to 60 days (5,184,000 seconds)", async function () { + it("(#1) Creates an account with an auto renew period set to 60 days (5,184,000 seconds)", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", @@ -413,7 +413,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#2) Creates an account with an auto renew period set to -1 seconds", async function () { + it("(#2) Creates an account with an auto renew period set to -1 seconds", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -425,7 +425,7 @@ describe("AccountCreateTransaction", function () { key: key.key, autoRenewPeriod: -1, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -434,7 +434,7 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Creates an account with an auto renew period set to the minimum period of 30 days (2,592,000 seconds)", async function () { + it("(#3) Creates an account with an auto renew period set to the minimum period of 30 days (2,592,000 seconds)", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", @@ -454,7 +454,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#4) Creates an account with an auto renew period set to the minimum period of 30 days minus one second (2,591,999 seconds)", async function () { + it("(#4) Creates an account with an auto renew period set to the minimum period of 30 days minus one second (2,591,999 seconds)", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", @@ -466,7 +466,7 @@ describe("AccountCreateTransaction", function () { key: key.key, autoRenewPeriod: 2591999, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); return; } @@ -475,7 +475,7 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Creates an account with an auto renew period set to the maximum period of 8,000,001 seconds", async function () { + it("(#5) Creates an account with an auto renew period set to the maximum period of 8,000,001 seconds", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", @@ -495,7 +495,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#6) Creates an account with an auto renew period set to the maximum period plus one seconds (8,000,002 seconds)", async function () { + it("(#6) Creates an account with an auto renew period set to the maximum period plus one seconds (8,000,002 seconds)", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -507,7 +507,7 @@ describe("AccountCreateTransaction", function () { key: key.key, autoRenewPeriod: 8000002, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); return; } @@ -517,22 +517,23 @@ describe("AccountCreateTransaction", function () { }); }); - describe("Memo", async function () { - async function verifyAccountCreationWithMemo(accountId, memo) { + describe("Memo", async () => { + const verifyAccountCreationWithMemo = async ( + accountId: string, + memo: string, + ) => { // If the account was created successfully, the queried account's memos should be equal. expect(memo).to.equal( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).accountMemo, + (await consensusInfoClient.getAccountInfo(accountId)).accountMemo, ); expect(memo).to.equal( await ( await mirrorNodeClient.getAccountData(accountId) ).memo, ); - } + }; - it("(#1) Creates an account with a valid memo", async function () { + it("(#1) Creates an account with a valid memo", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", @@ -549,7 +550,7 @@ describe("AccountCreateTransaction", function () { await verifyAccountCreationWithMemo(response.accountId, memo); }); - it("(#2) Creates an account with an empty memo", async function () { + it("(#2) Creates an account with an empty memo", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", @@ -566,7 +567,7 @@ describe("AccountCreateTransaction", function () { await verifyAccountCreationWithMemo(response.accountId, memo); }); - it("(#3) Creates an account with a memo that is 100 characters", async function () { + it("(#3) Creates an account with a memo that is 100 characters", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", @@ -584,7 +585,7 @@ describe("AccountCreateTransaction", function () { await verifyAccountCreationWithMemo(response.accountId, memo); }); - it("(#4) Creates an account with a memo that exceeds 100 characters", async function () { + it("(#4) Creates an account with a memo that exceeds 100 characters", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -596,7 +597,7 @@ describe("AccountCreateTransaction", function () { key: key.key, memo: "This is a long memo that is not valid because it exceeds 100 characters and it should fail the test!!", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "MEMO_TOO_LONG"); return; } @@ -605,7 +606,7 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Creates an account with an invalid memo", async function () { + it("(#5) Creates an account with an invalid memo", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -617,7 +618,7 @@ describe("AccountCreateTransaction", function () { key: key.key, memo: "This is an invalid memo!\0", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_ZERO_BYTE_IN_STRING"); return; } @@ -627,17 +628,16 @@ describe("AccountCreateTransaction", function () { }); }); - describe("Max Automatic Token Associations", async function () { - async function verifyAccountCreationWithMaxAutoTokenAssociations( - accountId, - maxAutomaticTokenAssociations, - ) { + describe("Max Automatic Token Associations", async () => { + const verifyAccountCreationWithMaxAutoTokenAssociations = async ( + accountId: string, + maxAutomaticTokenAssociations: number, + ) => { // If the account was created successfully, the queried account's max automatic token associations should be equal. expect(maxAutomaticTokenAssociations).to.equal( Number( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).maxAutomaticTokenAssociations, + (await consensusInfoClient.getAccountInfo(accountId)) + .maxAutomaticTokenAssociations, ), ); expect(maxAutomaticTokenAssociations).to.equal( @@ -645,9 +645,9 @@ describe("AccountCreateTransaction", function () { await mirrorNodeClient.getAccountData(accountId) ).max_automatic_token_associations, ); - } + }; - it("(#1) Creates an account with a max token association set to 100", async function () { + it("(#1) Creates an account with a max token association set to 100", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", @@ -670,7 +670,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#2) Creates an account with a max token association set to 0", async function () { + it("(#2) Creates an account with a max token association set to 0", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", @@ -690,7 +690,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#3) Creates an account with a max token association that is the maximum value", async function () { + it("(#3) Creates an account with a max token association that is the maximum value", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", @@ -710,7 +710,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#4) Creates an account with a max token association that is the maximum value plus one", async function () { + it("(#4) Creates an account with a max token association that is the maximum value plus one", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -722,7 +722,7 @@ describe("AccountCreateTransaction", function () { key: key.key, maxAutoTokenAssociations: 5001, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_MAX_AUTO_ASSOCIATIONS"); return; } @@ -732,42 +732,42 @@ describe("AccountCreateTransaction", function () { }); }); - describe("Staked ID", async function () { - async function verifyAccountCreationWithStakedAccountId( - accountId, - stakedAccountId, - ) { + describe("Staked ID", async () => { + const verifyAccountCreationWithStakedAccountId = async ( + accountId: string, + stakedAccountId: string, + ) => { // If the account was created successfully, the queried account's staked account IDs should be equal. expect(stakedAccountId).to.equal( - await ( + ( await consensusInfoClient.getAccountInfo(accountId) - ).stakingInfo.stakedAccountId.toString(), + ).stakingInfo?.stakedAccountId?.toString(), ); expect(stakedAccountId).to.equal( await ( await mirrorNodeClient.getAccountData(accountId) ).staked_account_id, ); - } + }; - async function verifyAccountCreationWithStakedNodeId( - accountId, - stakedNodeId, - ) { + const verifyAccountCreationWithStakedNodeId = async ( + accountId: string, + stakedNodeId: string, + ) => { // If the account was created successfully, the queried account's staked node IDs should be equal. - expect(stakedNodeId.toString()).to.equal( - await ( + expect(stakedNodeId).to.equal( + ( await consensusInfoClient.getAccountInfo(accountId) - ).stakingInfo.stakedNodeId.toString(), + ).stakingInfo?.stakedNodeId?.toString(), ); expect(stakedNodeId).to.equal( await ( await mirrorNodeClient.getAccountData(accountId) - ).staked_node_id, + ).staked_node_id.toString(), ); - } + }; - it("(#1) Creates an account with the staked account ID set to the operators account ID", async function () { + it("(#1) Creates an account with the staked account ID set to the operators account ID", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", @@ -782,18 +782,18 @@ describe("AccountCreateTransaction", function () { // Verify the account was created with the staked account ID equal to the operator account ID. await verifyAccountCreationWithStakedAccountId( response.accountId, - process.env.OPERATOR_ACCOUNT_ID, + process.env.OPERATOR_ACCOUNT_ID as string, ); }); - it("(#2) Creates an account with the staked node ID set to a valid node ID", async function () { + it("(#2) Creates an account with the staked node ID set to a valid node ID", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); // Attempt to create an account with the staked node ID set to the node's node ID. - const stakedNodeId = 0; + const stakedNodeId = "0"; const response = await JSONRPCRequest(this, "createAccount", { key: key.key, stakedNodeId, @@ -806,7 +806,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#3) Creates an account with the staked account ID set to an account ID that doesn't exist", async function () { + it("(#3) Creates an account with the staked account ID set to an account ID that doesn't exist", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -818,7 +818,7 @@ describe("AccountCreateTransaction", function () { key: key.key, stakedAccountId: "123.456.789", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_STAKING_ID"); return; } @@ -827,7 +827,7 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Creates an account with the staked node ID set to a node ID that doesn't exist", async function () { + it("(#4) Creates an account with the staked node ID set to a node ID that doesn't exist", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", @@ -837,9 +837,9 @@ describe("AccountCreateTransaction", function () { // Attempt to create an account with a staked node ID that doesn't exist. The network should respond with an INVALID_STAKING_ID status. await JSONRPCRequest(this, "createAccount", { key: key.key, - stakedNodeId: 123456789, + stakedNodeId: "123456789", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_STAKING_ID"); return; } @@ -848,7 +848,7 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Creates an account with the staked account ID set to an empty account ID", async function () { + it("(#5) Creates an account with the staked account ID set to an empty account ID", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", @@ -860,7 +860,7 @@ describe("AccountCreateTransaction", function () { key: key.key, stakedAccountId: "", }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -869,7 +869,7 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Creates an account with the staked node ID set to an invalid node ID", async function () { + it("(#6) Creates an account with the staked node ID set to an invalid node ID", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", @@ -879,9 +879,9 @@ describe("AccountCreateTransaction", function () { // Attempt to create an account with an invalid staked node ID. The network should respond with an INVALID_STAKING_ID status. await JSONRPCRequest(this, "createAccount", { key: key.key, - stakedNodeId: -100, + stakedNodeId: "-100", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_STAKING_ID"); return; } @@ -890,14 +890,14 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Creates an account with a staked account ID and a staked node ID", async function () { + it("(#7) Creates an account with a staked account ID and a staked node ID", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); // Attempt to create an account with a staked account ID and a staked node ID. - const stakedNodeId = 0; + const stakedNodeId = "0"; const response = await JSONRPCRequest(this, "createAccount", { key: key.key, stakedAccountId: process.env.OPERATOR_ACCOUNT_ID, @@ -912,25 +912,24 @@ describe("AccountCreateTransaction", function () { }); }); - describe("Decline Rewards", async function () { - async function verifyAccountCreationWithDeclineRewards( - accountId, - declineRewards, - ) { + describe("Decline Rewards", async () => { + const verifyAccountCreationWithDeclineRewards = async ( + accountId: string, + declineRewards: boolean, + ) => { // If the account was created successfully, the queried account's decline rewards policy should be equal. expect(declineRewards).to.equal( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).stakingInfo.declineStakingReward, + (await consensusInfoClient.getAccountInfo(accountId)).stakingInfo + ?.declineStakingReward, ); expect(declineRewards).to.equal( await ( await mirrorNodeClient.getAccountData(accountId) ).decline_reward, ); - } + }; - it("(#1) Creates an account that declines staking rewards", async function () { + it("(#1) Creates an account that declines staking rewards", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", @@ -950,7 +949,7 @@ describe("AccountCreateTransaction", function () { ); }); - it("(#2) Creates an account that doesn't decline staking rewards", async function () { + it("(#2) Creates an account that doesn't decline staking rewards", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", @@ -971,13 +970,14 @@ describe("AccountCreateTransaction", function () { }); }); - describe("Alias", async function () { - async function verifyAccountCreationWithAlias(accountId, alias) { + describe("Alias", async () => { + const verifyAccountCreationWithAlias = async ( + accountId: string, + alias: string, + ) => { // If the account was created successfully, the queried account's aliases should be equal. expect(alias).to.equal( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).contractAccountId, + (await consensusInfoClient.getAccountInfo(accountId)).contractAccountId, ); expect("0x" + alias).to.equal( @@ -985,9 +985,9 @@ describe("AccountCreateTransaction", function () { await mirrorNodeClient.getAccountData(accountId) ).evm_address, ); - } + }; - it("(#1) Creates an account with the keccak-256 hash of an ECDSAsecp256k1 public key", async function () { + it("(#1) Creates an account with the keccak-256 hash of an ECDSAsecp256k1 public key", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", @@ -996,8 +996,8 @@ describe("AccountCreateTransaction", function () { // Generate the ECDSAsecp256k1 private key of the alias for the account. //prettier-ignore const ecdsaSecp256k1PrivateKey = await JSONRPCRequest(this, "generateKey", { - type: "ecdsaSecp256k1PrivateKey", - }); + type: "ecdsaSecp256k1PrivateKey", + }); // Generate the EVM address associated with the private key, which will then be used as the alias for the account. const alias = await JSONRPCRequest(this, "generateKey", { @@ -1018,7 +1018,7 @@ describe("AccountCreateTransaction", function () { await verifyAccountCreationWithAlias(response.accountId, alias.key); }); - it("(#2) Creates an account with the keccak-256 hash of an ECDSAsecp256k1 public key without a signature", async function () { + it("(#2) Creates an account with the keccak-256 hash of an ECDSAsecp256k1 public key without a signature", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -1035,7 +1035,7 @@ describe("AccountCreateTransaction", function () { key: key.key, alias: alias.key, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -1044,7 +1044,7 @@ describe("AccountCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Creates an account with an invalid alias", async function () { + it("(#3) Creates an account with an invalid alias", async () => { // Generate a valid key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", @@ -1056,7 +1056,7 @@ describe("AccountCreateTransaction", function () { key: key.key, alias: "0x" + crypto.randomBytes(20).toString("hex").toUpperCase(), }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } diff --git a/test/crypto-service/test_accountDeleteTransaction.js b/src/tests/crypto-service/test-account-delete-transaction.ts similarity index 85% rename from test/crypto-service/test_accountDeleteTransaction.js rename to src/tests/crypto-service/test-account-delete-transaction.ts index a7f0ebc..54405b6 100644 --- a/test/crypto-service/test_accountDeleteTransaction.js +++ b/src/tests/crypto-service/test-account-delete-transaction.ts @@ -1,21 +1,22 @@ import { assert } from "chai"; -import { JSONRPCRequest } from "../../client.js"; -import consensusInfoClient from "../../consensusInfoClient.js"; -import { setOperator } from "../../setup_Tests.js"; +import { JSONRPCRequest } from "@services/Client"; +import consensusInfoClient from "@services/ConsensusInfoClient"; +import { setOperator } from "@helpers/setup-tests"; describe("AccountDeleteTransaction", function () { // Tests should not take longer than 30 seconds to fully execute. this.timeout(30000); // An account is created for each test. These hold the information for that account. - let accountPrivateKey, accountId; + let accountPrivateKey: string, accountId: string; - beforeEach(async function () { + beforeEach(async () => { // Initialize the network and operator. await setOperator( - process.env.OPERATOR_ACCOUNT_ID, - process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + this, + process.env.OPERATOR_ACCOUNT_ID as string, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY as string, ); // Generate a private key. @@ -32,21 +33,21 @@ describe("AccountDeleteTransaction", function () { accountId = response.accountId; }); - afterEach(async function () { + afterEach(async () => { await JSONRPCRequest(this, "reset"); }); - describe("Delete Account Id", async function () { - it("(#1) Deletes an account with no transfer account", async function () { + describe("Delete Account Id", async () => { + it("(#1) Deletes an account with no transfer account", async () => { try { // Attempt to delete the account without a transfer account. The network should respond with an ACCOUNT_ID_DOES_NOT_EXIST status. - const response = await JSONRPCRequest(this, "deleteAccount", { + await JSONRPCRequest(this, "deleteAccount", { deleteAccountId: accountId, commonTransactionParams: { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "ACCOUNT_ID_DOES_NOT_EXIST"); return; } @@ -55,7 +56,7 @@ describe("AccountDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Deletes an account with no delete account", async function () { + it("(#2) Deletes an account with no delete account", async () => { try { // Attempt to delete the account without a delete account. The network should respond with an ACCOUNT_ID_DOES_NOT_EXIST status. await JSONRPCRequest(this, "deleteAccount", { @@ -64,7 +65,7 @@ describe("AccountDeleteTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "ACCOUNT_ID_DOES_NOT_EXIST"); return; } @@ -73,17 +74,17 @@ describe("AccountDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Deletes an admin account", async function () { + it("(#3) Deletes an admin account", async () => { try { // Attempt to delete an admin account. The network should respond with an ENTITY_NOT_ALLOWED_TO_DELETE status. - const response = await JSONRPCRequest(this, "deleteAccount", { + await JSONRPCRequest(this, "deleteAccount", { deleteAccountId: "0.0.2", transferAccountId: process.env.OPERATOR_ACCOUNT_ID, commonTransactionParams: { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "ENTITY_NOT_ALLOWED_TO_DELETE"); return; } @@ -92,7 +93,7 @@ describe("AccountDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Deletes an account that doesn't exist", async function () { + it("(#4) Deletes an account that doesn't exist", async () => { try { // Attempt to delete an account that doesn't exist. The network should respond with an INVALID_ACCOUNT_ID status. await JSONRPCRequest(this, "deleteAccount", { @@ -102,7 +103,7 @@ describe("AccountDeleteTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_ACCOUNT_ID"); return; } @@ -111,7 +112,7 @@ describe("AccountDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Deletes an account that was already deleted", async function () { + it("(#5) Deletes an account that was already deleted", async () => { // Delete the account first. let response = await JSONRPCRequest(this, "deleteAccount", { deleteAccountId: accountId, @@ -130,7 +131,7 @@ describe("AccountDeleteTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "ACCOUNT_DELETED"); return; } @@ -139,14 +140,14 @@ describe("AccountDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Deletes an account without signing with the account's private key", async function () { + it("(#6) Deletes an account without signing with the account's private key", async () => { try { // Attempt to delete the account without signing with the account's private key. The network should respond with an INVALID_SIGNATURE status. await JSONRPCRequest(this, "deleteAccount", { deleteAccountId: accountId, transferAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -155,7 +156,7 @@ describe("AccountDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Deletes an account but signs with an incorrect private key", async function () { + it("(#7) Deletes an account but signs with an incorrect private key", async () => { // Generate a private key. const key = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -163,14 +164,14 @@ describe("AccountDeleteTransaction", function () { try { // Attempt to delete the account and sign with an incorrect private key. The network should respond with an INVALID_SIGNATURE status. - const response = await JSONRPCRequest(this, "deleteAccount", { + await JSONRPCRequest(this, "deleteAccount", { deleteAccountId: accountId, transferAccountId: process.env.OPERATOR_ACCOUNT_ID, commonTransactionParams: { signers: [key.key], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -180,10 +181,10 @@ describe("AccountDeleteTransaction", function () { }); }); - describe("Transfer Account Id", async function () { - it("(#1) Deletes an account with a valid transfer account", async function () { + describe("Transfer Account Id", async () => { + it("(#1) Deletes an account with a valid transfer account", async () => { // Attempt to delete the account and transfer its funds to the operator account. - const response = await JSONRPCRequest(this, "deleteAccount", { + await JSONRPCRequest(this, "deleteAccount", { deleteAccountId: accountId, transferAccountId: process.env.OPERATOR_ACCOUNT_ID, commonTransactionParams: { @@ -195,7 +196,7 @@ describe("AccountDeleteTransaction", function () { // AccountInfoQuery throws if the account is deleted, so catch that and verify the status code maps correctly. try { await consensusInfoClient.getAccountInfo(accountId); - } catch (err) { + } catch (err: any) { assert.equal(err.status._code, 72); // 72 maps to ACCOUNT_DELETED return; } @@ -204,7 +205,7 @@ describe("AccountDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Deletes an account with a transfer account that is the deleted account", async function () { + it("(#2) Deletes an account with a transfer account that is the deleted account", async () => { try { // Attempt to delete the account with a transfer account that is the deleted account. The network should respond with an TRANSFER_ACCOUNT_SAME_AS_DELETE_ACCOUNT status. await JSONRPCRequest(this, "deleteAccount", { @@ -214,7 +215,7 @@ describe("AccountDeleteTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal( err.data.status, "TRANSFER_ACCOUNT_SAME_AS_DELETE_ACCOUNT", @@ -226,17 +227,17 @@ describe("AccountDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Deletes an account with a transfer account that is invalid/doesn't exist", async function () { + it("(#3) Deletes an account with a transfer account that is invalid/doesn't exist", async () => { try { // Attempt to delete the account with a transfer account that is the deleted account. The network should respond with an INVALID_TRANSFER_ACCOUNT_ID status. - const response = await JSONRPCRequest(this, "deleteAccount", { + await JSONRPCRequest(this, "deleteAccount", { deleteAccountId: accountId, transferAccountId: "123.456.789", commonTransactionParams: { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TRANSFER_ACCOUNT_ID"); return; } @@ -245,7 +246,7 @@ describe("AccountDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Deletes an account with a transfer account that is a deleted account", async function () { + it("(#4) Deletes an account with a transfer account that is a deleted account", async () => { // Generate a key. var response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", @@ -276,7 +277,7 @@ describe("AccountDeleteTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "ACCOUNT_DELETED"); return; } diff --git a/test/crypto-service/test_accountUpdateTransaction.js b/src/tests/crypto-service/test-account-update-transaction.ts similarity index 85% rename from test/crypto-service/test_accountUpdateTransaction.js rename to src/tests/crypto-service/test-account-update-transaction.ts index ef46881..3452e4b 100644 --- a/test/crypto-service/test_accountUpdateTransaction.js +++ b/src/tests/crypto-service/test-account-update-transaction.ts @@ -1,34 +1,37 @@ import { expect, assert } from "chai"; +import { PublicKey, StatusError } 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 { JSONRPCRequest } from "@services/Client"; +import mirrorNodeClient from "@services/MirrorNodeClient"; +import consensusInfoClient from "@services/ConsensusInfoClient"; +import { setOperator } from "@helpers/setup-tests"; +import { retryOnError } from "@helpers/retry-on-error"; +import { getRawKeyFromHex } from "@helpers/asn1-decoder"; import { getEncodedKeyHexFromKeyListConsensus, getPublicKeyFromMirrorNode, -} from "../../utils/helpers/key.js"; -import { retryOnError } from "../../utils/helpers/retry-on-error.js"; -import { getRawKeyFromHex } from "../../utils/helpers/asn1-decoder.js"; +} from "@helpers/key"; + import { - twoLevelsNestedKeyListParams, fourKeysKeyListParams, + twoLevelsNestedKeyListParams, twoThresholdKeyParams, -} from "../../utils/helpers/constants/key-list.js"; +} from "@constants/key-list"; describe("AccountUpdateTransaction", function () { // Tests should not take longer than 30 seconds to fully execute. this.timeout(30000); // An account is created for each test. These hold the information for that account. - let accountPrivateKey, accountId; + let accountPrivateKey: string, accountId: string; - beforeEach(async function () { + beforeEach(async () => { // Initialize the network and operator. await setOperator( - process.env.OPERATOR_ACCOUNT_ID, - process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + this, + process.env.OPERATOR_ACCOUNT_ID as string, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY as string, ); // Generate a private key. @@ -45,12 +48,12 @@ describe("AccountUpdateTransaction", function () { accountId = response.accountId; }); - afterEach(async function () { + afterEach(async () => { await JSONRPCRequest(this, "reset"); }); - describe("AccountId", async function () { - it("(#1) Updates an account with no updates", async function () { + describe("AccountId", async () => { + it("(#1) Updates an account with no updates", async () => { // Attempt to update the account. await JSONRPCRequest(this, "updateAccount", { accountId: accountId, @@ -67,13 +70,13 @@ describe("AccountUpdateTransaction", function () { expect(accountId).to.be.equal(consensusNodeData.accountId.toString()); }); - it("(#2) Updates an account with no updates without signing with the account's private key", async function () { + it("(#2) Updates an account with no updates without signing with the account's private key", async () => { try { // Attempt to update the account without signing with the account's private key. The network should respond with an INVALID_SIGNATURE status. await JSONRPCRequest(this, "updateAccount", { accountId: accountId, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -82,11 +85,11 @@ describe("AccountUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Updates an account with no account ID", async function () { + it("(#3) Updates an account with no account ID", async () => { try { // Attempt to update the account without providing the account ID. The network should respond with an ACCOUNT_ID_DOES_NOT_EXIST status. await JSONRPCRequest(this, "updateAccount", {}); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "ACCOUNT_ID_DOES_NOT_EXIST"); return; } @@ -96,16 +99,19 @@ describe("AccountUpdateTransaction", function () { }); }); - describe("Key", async function () { - async function verifyAccountUpdateKey(accountId, updatedKey) { + describe("Key", () => { + const verifyAccountUpdateKey = async ( + accountId: string, + updatedKey: string, + ) => { // If the account was updated successfully, the queried account keys should be equal. const rawKey = getRawKeyFromHex(updatedKey); // Consensus node check expect(rawKey).to.equal( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).key._key.toStringRaw(), + ( + (await consensusInfoClient.getAccountInfo(accountId)).key as PublicKey + ).toStringRaw(), ); const publicKeyMirrorNode = await getPublicKeyFromMirrorNode( @@ -115,10 +121,13 @@ describe("AccountUpdateTransaction", function () { ); // Mirror node check - expect(rawKey).to.equal(publicKeyMirrorNode.toStringRaw()); - } + expect(rawKey).to.equal(publicKeyMirrorNode?.toStringRaw()); + }; - async function verifyAccountUpdateKeyList(accountId, updatedKey) { + const verifyAccountUpdateKeyList = async ( + accountId: string, + updatedKey: string, + ) => { const keyHex = await getEncodedKeyHexFromKeyListConsensus( "getAccountInfo", accountId, @@ -142,9 +151,9 @@ describe("AccountUpdateTransaction", function () { // Removing the unnecessary prefix from the mirror node key mirrorNodeKey.slice(mirrorNodeKey.length - updatedKey.length), ); - } + }; - it("(#1) Updates the key of an account to a new valid ED25519 public key", async function () { + it("(#1) Updates the key of an account to a new valid ED25519 public key", async () => { // Generate a new ED25519 private key for the account. const ed25519PrivateKey = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -171,7 +180,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#2) Updates the key of an account to a new valid ECDSAsecp256k1 public key", async function () { + it("(#2) Updates the key of an account to a new valid ECDSAsecp256k1 public key", async () => { // Generate a new ECDSAsecp256k1 private key for the account. const ecdsaSecp256k1PrivateKey = await JSONRPCRequest( this, @@ -203,7 +212,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#3) Updates the key of an account to a new valid ED25519 private key", async function () { + it("(#3) Updates the key of an account to a new valid ED25519 private key", async () => { // Generate a new ED25519 private key for the account. const ed25519PrivateKey = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -230,7 +239,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#4) Updates the key of an account to a new valid ECDSAsecp256k1 private key", async function () { + it("(#4) Updates the key of an account to a new valid ECDSAsecp256k1 private key", async () => { // Generate a new ECDSAsecp256k1 private key for the account. const ecdsaSecp256k1PrivateKey = await JSONRPCRequest( this, @@ -265,7 +274,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#5) Updates the key of an account to a new valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys", async function () { + it("(#5) Updates the key of an account to a new valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys", async () => { // Generate a KeyList of ED25519 and ECDSAsecp256k1 private and public keys for the account. const keyList = await JSONRPCRequest( this, @@ -294,7 +303,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#6) Updates the key of an account to a new valid KeyList of nested KeyLists (three levels)", async function () { + it("(#6) Updates the key of an account to a new valid KeyList of nested KeyLists (three levels)", async () => { // Generate a KeyList of nested KeyLists of ED25519 and ECDSAsecp256k1 private and public keys for the account. const nestedKeyList = await JSONRPCRequest( this, @@ -325,7 +334,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#7) Updates the key of an account to a new valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys", async function () { + it("(#7) Updates the key of an account to a new valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys", async () => { // Generate a ThresholdKey of nested KeyLists of ED25519 and ECDSAsecp256k1 private and public keys for the account. const thresholdKey = await JSONRPCRequest( this, @@ -352,7 +361,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#8) Updates the key of an account to a key without signing with the new key", async function () { + it("(#8) Updates the key of an account to a key without signing with the new key", async () => { // Generate a new key for the account. const key = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", @@ -367,7 +376,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -376,7 +385,7 @@ describe("AccountUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#9) Updates the key of an account to a new public key and signs with an incorrect private key", async function () { + it("(#9) Updates the key of an account to a new public key and signs with an incorrect private key", async () => { // Generate a new public key for the account. const publicKey = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", @@ -396,7 +405,7 @@ describe("AccountUpdateTransaction", function () { signers: [privateKey.key], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -406,14 +415,15 @@ describe("AccountUpdateTransaction", function () { }); }); - describe("Auto Renew Period", async function () { - async function verifyAccountAutoRenewPeriodUpdate(autoRenewPeriodSeconds) { + describe("Auto Renew Period", () => { + const verifyAccountAutoRenewPeriodUpdate = async ( + autoRenewPeriodSeconds: number, + ) => { // If the account was updated successfully, the queried account's auto renew periods should be equal. expect(autoRenewPeriodSeconds).to.equal( Number( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).autoRenewPeriod.seconds, + (await consensusInfoClient.getAccountInfo(accountId)).autoRenewPeriod + .seconds, ), ); expect(autoRenewPeriodSeconds).to.equal( @@ -421,9 +431,9 @@ describe("AccountUpdateTransaction", function () { await mirrorNodeClient.getAccountData(accountId) ).auto_renew_period, ); - } + }; - it("(#1) Updates the auto-renew period of an account to 60 days (5,184,000 seconds)", async function () { + it("(#1) Updates the auto-renew period of an account to 60 days (5,184,000 seconds)", async () => { // Attempt to update the auto-renew period of the account 60 days. const autoRenewPeriodSeconds = 5184000; await JSONRPCRequest(this, "updateAccount", { @@ -435,12 +445,12 @@ describe("AccountUpdateTransaction", function () { }); // Verify the account was updated with an auto-renew period set to 60 days. - await retryOnError(async () => + await retryOnError(() => verifyAccountAutoRenewPeriodUpdate(autoRenewPeriodSeconds), ); }); - it("(#2) Updates the auto-renew period of an account to -1 seconds", async function () { + it("(#2) Updates the auto-renew period of an account to -1 seconds", async () => { try { // Attempt to update the auto-renew period of the account to -1 seconds. The network should respond with an INVALID_RENEWAL_PERIOD status. await JSONRPCRequest(this, "updateAccount", { @@ -450,7 +460,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -459,7 +469,7 @@ describe("AccountUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Updates the auto-renew period of an account to 30 days (2,592,000 seconds)", async function () { + it("(#3) Updates the auto-renew period of an account to 30 days (2,592,000 seconds)", async () => { // Attempt to update the auto-renew period of the account to 30 days. const autoRenewPeriodSeconds = 2592000; await JSONRPCRequest(this, "updateAccount", { @@ -476,7 +486,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#4) Updates the auto-renew period of an account to 30 days minus one second (2,591,999 seconds)", async function () { + it("(#4) Updates the auto-renew period of an account to 30 days minus one second (2,591,999 seconds)", async () => { try { // Attempt to update the auto-renew period of the account to 2,591,999 seconds. The network should respond with an AUTORENEW_DURATION_NOT_IN_RANGE status. await JSONRPCRequest(this, "updateAccount", { @@ -486,7 +496,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); return; } @@ -495,7 +505,7 @@ describe("AccountUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Updates the auto-renew period of an account to the maximum period of 8,000,001 seconds", async function () { + it("(#5) Updates the auto-renew period of an account to the maximum period of 8,000,001 seconds", async () => { // Attempt to update the auto-renew period of the account to 8,000,001 seconds. const autoRenewPeriodSeconds = 8000001; await JSONRPCRequest(this, "updateAccount", { @@ -512,7 +522,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#6) Updates the auto-renew period of an account to the maximum period plus one second (8,000,002 seconds)", async function () { + it("(#6) Updates the auto-renew period of an account to the maximum period plus one second (8,000,002 seconds)", async () => { try { // Attempt to update auto-renew period of the account to 8,000,002 seconds. The network should respond with an AUTORENEW_DURATION_NOT_IN_RANGE status. await JSONRPCRequest(this, "updateAccount", { @@ -522,7 +532,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "AUTORENEW_DURATION_NOT_IN_RANGE"); return; } @@ -532,14 +542,15 @@ describe("AccountUpdateTransaction", function () { }); }); - describe("Expiration Time", async function () { - async function verifyAccountExpirationTimeUpdate(expirationTime) { + describe("Expiration Time", async () => { + const verifyAccountExpirationTimeUpdate = async ( + expirationTime: number, + ) => { // If the account was updated successfully, the queried account's expiration times should be equal. expect(expirationTime).to.equal( Number( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).expirationTime.seconds, + (await consensusInfoClient.getAccountInfo(accountId)).expirationTime + .seconds, ), ); expect(expirationTime).to.equal( @@ -549,11 +560,11 @@ describe("AccountUpdateTransaction", function () { ).expiry_timestamp, ), ); - } + }; - it("(#1) Updates the expiration time of an account to 8,000,001 seconds from the current time", async function () { + it("(#1) Updates the expiration time of an account to 8,000,001 seconds from the current time", async () => { // Attempt to update the expiration time of the account to 8,000,001 seconds from the current time. - const expirationTimeSeconds = parseInt(Date.now() / 1000 + 8000001); + const expirationTimeSeconds = Math.floor(Date.now() / 1000 + 8000001); await JSONRPCRequest(this, "updateAccount", { accountId: accountId, expirationTime: expirationTimeSeconds, @@ -568,7 +579,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#2) Updates the expiration time of an account to -1 seconds", async function () { + it("(#2) Updates the expiration time of an account to -1 seconds", async () => { try { // Attempt to update the expiration time of the account to -1 seconds. The network should respond with an INVALID_EXPIRATION_TIME status. await JSONRPCRequest(this, "updateAccount", { @@ -578,7 +589,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -587,7 +598,7 @@ describe("AccountUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Updates the expiration time of an account to 1 second less than its current expiration time", async function () { + it("(#3) Updates the expiration time of an account to 1 second less than its current expiration time", async () => { // Get the account's expiration time. const accountInfo = await mirrorNodeClient.getAccountData(accountId); const expirationTimeSeconds = await accountInfo.expiry_timestamp; @@ -596,12 +607,12 @@ describe("AccountUpdateTransaction", function () { try { await JSONRPCRequest(this, "updateAccount", { accountId: accountId, - expirationTime: parseInt(Number(expirationTimeSeconds) - 1), + expirationTime: Math.floor(Number(expirationTimeSeconds) - 1), commonTransactionParams: { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "EXPIRATION_REDUCTION_NOT_ALLOWED"); return; } @@ -610,7 +621,7 @@ describe("AccountUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Updates the expiration time of an account to 8,000,002 seconds from the current time", async function () { + it("(#4) Updates the expiration time of an account to 8,000,002 seconds from the current time", async () => { try { // Attempt to update the expiration time of the account to 8,000,002 seconds from the current time. The network should respond with an INVALID_EXPIRATION_TIME status. const response = await JSONRPCRequest(this, "updateAccount", { @@ -620,8 +631,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -631,24 +641,23 @@ describe("AccountUpdateTransaction", function () { }); }); - describe("Receiver Signature Required", async function () { - async function verifyAccountReceiverSignatureRequiredUpdate( - receiverSignatureRequired, - ) { + describe("Receiver Signature Required", async () => { + const verifyAccountReceiverSignatureRequiredUpdate = async ( + receiverSignatureRequired: boolean, + ) => { // If the account was updated successfully, the queried account's receiver signature required policies should be equal. expect(receiverSignatureRequired).to.equal( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).isReceiverSignatureRequired, + (await consensusInfoClient.getAccountInfo(accountId)) + .isReceiverSignatureRequired, ); expect(receiverSignatureRequired).to.equal( await ( await mirrorNodeClient.getAccountData(accountId) ).receiver_sig_required, ); - } + }; - it("(#1) Updates the receiver signature required policy of an account to require a receiving signature", async function () { + it("(#1) Updates the receiver signature required policy of an account to require a receiving signature", async () => { // Attempt to update the receiver signature required policy of the account to require a signature when receiving. const receiverSignatureRequired = true; await JSONRPCRequest(this, "updateAccount", { @@ -665,7 +674,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#2) Updates the receiver signature required policy of an account to not require a receiving signature", async function () { + it("(#2) Updates the receiver signature required policy of an account to not require a receiving signature", async () => { // Attempt to update the receiver signature required policy of the account to not require a signature when receiving. const receiverSignatureRequired = false; await JSONRPCRequest(this, "updateAccount", { @@ -683,22 +692,20 @@ describe("AccountUpdateTransaction", function () { }); }); - describe("Memo", async function () { - async function verifyAccountMemoUpdate(memo) { + describe("Memo", async () => { + const verifyAccountMemoUpdate = async (memo: string) => { // If the account was updated successfully, the queried account's memos should be equal. expect(memo).to.equal( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).accountMemo, + (await consensusInfoClient.getAccountInfo(accountId)).accountMemo, ); expect(memo).to.equal( await ( await mirrorNodeClient.getAccountData(accountId) ).memo, ); - } + }; - it("(#1) Updates the memo of an account to a memo that is a valid length", async function () { + it("(#1) Updates the memo of an account to a memo that is a valid length", async () => { // Attempt to update the memo of the account to a memo that is a valid length. const memo = "testmemo"; await JSONRPCRequest(this, "updateAccount", { @@ -713,7 +720,7 @@ describe("AccountUpdateTransaction", function () { await retryOnError(async () => verifyAccountMemoUpdate(memo)); }); - it("(#2) Updates the memo of an account to a memo that is the minimum length", async function () { + it("(#2) Updates the memo of an account to a memo that is the minimum length", async () => { // Attempt to update the memo of the account with a memo that is the minimum length. const memo = ""; await JSONRPCRequest(this, "updateAccount", { @@ -728,7 +735,7 @@ describe("AccountUpdateTransaction", function () { await retryOnError(async () => verifyAccountMemoUpdate(memo)); }); - it("(#3) Updates the memo of an account to a memo that is the maximum length", async function () { + it("(#3) Updates the memo of an account to a memo that is the maximum length", async () => { // Attempt to update the memo of the account with a memo that is the maximum length. const memo = "This is a really long memo but it is still valid because it is 100 characters exactly on the money!!"; @@ -744,7 +751,7 @@ describe("AccountUpdateTransaction", function () { await retryOnError(async () => verifyAccountMemoUpdate(memo)); }); - it("(#4) Updates the memo of an account to a memo that exceeds the maximum length", async function () { + it("(#4) Updates the memo of an account to a memo that exceeds the maximum length", async () => { try { // Attempt to update the memo of the account with a memo that exceeds the maximum length. The network should respond with a MEMO_TOO_LONG status. await JSONRPCRequest(this, "updateAccount", { @@ -754,7 +761,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "MEMO_TOO_LONG"); return; } @@ -764,16 +771,15 @@ describe("AccountUpdateTransaction", function () { }); }); - describe("Max Automatic Token Associations", async function () { - async function verifyMaxAutoTokenAssociationsUpdate( - maxAutomaticTokenAssociations, - ) { + describe("Max Automatic Token Associations", async () => { + const verifyMaxAutoTokenAssociationsUpdate = async ( + maxAutomaticTokenAssociations: number, + ) => { // If the account was updated successfully, the queried account's max automatic token associations should be equal. expect(maxAutomaticTokenAssociations).to.equal( Number( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).maxAutomaticTokenAssociations, + (await consensusInfoClient.getAccountInfo(accountId)) + .maxAutomaticTokenAssociations, ), ); expect(maxAutomaticTokenAssociations).to.equal( @@ -783,9 +789,9 @@ describe("AccountUpdateTransaction", function () { ).max_automatic_token_associations, ), ); - } + }; - it("(#1) Updates the max automatic token associations of an account to a valid amount", async function () { + it("(#1) Updates the max automatic token associations of an account to a valid amount", async () => { // Attempt to update the max automatic token associations of the account to 100. const maxAutoTokenAssociations = 100; await JSONRPCRequest(this, "updateAccount", { @@ -803,7 +809,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#2) Updates the max automatic token associations of an account to the minimum amount", async function () { + it("(#2) Updates the max automatic token associations of an account to the minimum amount", async () => { // Attempt to update the max automatic token associations of the account to 0. const maxAutoTokenAssociations = 0; await JSONRPCRequest(this, "updateAccount", { @@ -820,7 +826,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#3) Updates the max automatic token associations of an account to the maximum amount", async function () { + it("(#3) Updates the max automatic token associations of an account to the maximum amount", async () => { // Attempt to update the max automatic token associations of the account to 5000. const maxAutoTokenAssociations = 5000; await JSONRPCRequest(this, "updateAccount", { @@ -838,7 +844,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#4) Updates the max automatic token associations of an account to an amount that exceeds the maximum amount", async function () { + it("(#4) Updates the max automatic token associations of an account to an amount that exceeds the maximum amount", async () => { try { // Attempt to update the max automatic token associations of the account to 5001. The network should respond with a REQUESTED_NUM_AUTOMATIC_ASSOCIATIONS_EXCEEDS_ASSOCIATION_LIMIT status. await JSONRPCRequest(this, "updateAccount", { @@ -849,7 +855,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal( err.data.status, "REQUESTED_NUM_AUTOMATIC_ASSOCIATIONS_EXCEEDS_ASSOCIATION_LIMIT", @@ -862,42 +868,43 @@ describe("AccountUpdateTransaction", function () { }); }); - describe("Staked ID", async function () { - async function verifyAccountStakedAccountIdUpdate(stakedAccountId) { + describe("Staked ID", async () => { + const verifyAccountStakedAccountIdUpdate = async ( + stakedAccountId: string, + ) => { // If the account was updated successfully, the queried account's staked account IDs should be equal. expect(stakedAccountId.toString()).to.equal( - await ( + ( await consensusInfoClient.getAccountInfo(accountId) - ).stakingInfo.stakedAccountId.toString(), + ).stakingInfo?.stakedAccountId?.toString(), ); expect(stakedAccountId).to.equal( await ( await mirrorNodeClient.getAccountData(accountId) ).staked_account_id, ); - } + }; - async function verifyAccountStakedNodeIdUpdate(stakedAccountId) { + const verifyAccountStakedNodeIdUpdate = async (stakedAccountId: string) => { // If the account was updated successfully, the queried account's staked node IDs should be equal. - expect(stakedAccountId).to.equal( + expect(+stakedAccountId).to.equal( Number( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).stakingInfo.stakedNodeId, + (await consensusInfoClient.getAccountInfo(accountId)).stakingInfo + ?.stakedNodeId, ), ); - expect(stakedAccountId).to.equal( + expect(+stakedAccountId).to.equal( Number( await ( await mirrorNodeClient.getAccountData(accountId) ).staked_account_id, ), ); - } + }; - it("(#1) Updates the staked account ID of an account to the operator's account ID", async function () { + it("(#1) Updates the staked account ID of an account to the operator's account ID", async () => { // Attempt to update the staked account ID of the account to the operator's account ID. - const stakedAccountId = process.env.OPERATOR_ACCOUNT_ID; + const stakedAccountId = process.env.OPERATOR_ACCOUNT_ID as string; await JSONRPCRequest(this, "updateAccount", { accountId: accountId, stakedAccountId: stakedAccountId, @@ -912,7 +919,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#2) Updates the staked node ID of an account to a valid node ID", async function () { + it("(#2) Updates the staked node ID of an account to a valid node ID", async () => { // Attempt to update the staked node ID of the account to a valid node ID. const stakedNodeId = 0; await JSONRPCRequest(this, "updateAccount", { @@ -925,11 +932,11 @@ describe("AccountUpdateTransaction", function () { // Verify the staked node ID of the account was updated. await retryOnError(async () => - verifyAccountStakedNodeIdUpdate(stakedNodeId), + verifyAccountStakedNodeIdUpdate(stakedNodeId.toString()), ); }); - it("(#3) Updates the staked account ID of an account to an account ID that doesn't exist", async function () { + it("(#3) Updates the staked account ID of an account to an account ID that doesn't exist", async () => { try { // Attempt to update the staked account ID of the account to an account ID that doesn't exist. The network should respond with an INVALID_STAKING_ID status. await JSONRPCRequest(this, "updateAccount", { @@ -939,7 +946,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_STAKING_ID"); return; } @@ -948,7 +955,7 @@ describe("AccountUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Updates the staked node ID of an account to a node ID that doesn't exist", async function () { + it("(#4) Updates the staked node ID of an account to a node ID that doesn't exist", async () => { try { // Attempt to update the staked node ID of the account to a node ID that doesn't exist. The network should respond with an INVALID_STAKING_ID status. await JSONRPCRequest(this, "updateAccount", { @@ -958,7 +965,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_STAKING_ID"); return; } @@ -967,7 +974,7 @@ describe("AccountUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Updates the staked account ID of an account to an empty account ID", async function () { + it("(#5) Updates the staked account ID of an account to an empty account ID", async () => { try { // Attempt to update the staked account ID of the account to an empty account ID. The SDK should throw an internal error. await JSONRPCRequest(this, "updateAccount", { @@ -977,7 +984,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -986,7 +993,7 @@ describe("AccountUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Updates the staked node ID of an account to an invalid node ID", async function () { + it("(#6) Updates the staked node ID of an account to an invalid node ID", async () => { try { // Attempt to update the staked node ID of the account to an invalid node ID. The network should respond with an INVALID_STAKING_ID status. await JSONRPCRequest(this, "updateAccount", { @@ -996,7 +1003,7 @@ describe("AccountUpdateTransaction", function () { signers: [accountPrivateKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_STAKING_ID"); return; } @@ -1006,20 +1013,19 @@ describe("AccountUpdateTransaction", function () { }); }); - describe("Decline Reward", async function () { - async function verifyDeclineRewardUpdate(declineRewards) { + describe("Decline Reward", async () => { + const verifyDeclineRewardUpdate = async (declineRewards: boolean) => { // If the account was updated successfully, the queried account's decline staking rewards policy should be equal. expect(declineRewards).to.equal( - await ( - await consensusInfoClient.getAccountInfo(accountId) - ).stakingInfo.declineStakingReward, + (await consensusInfoClient.getAccountInfo(accountId)).stakingInfo + ?.declineStakingReward, ); expect(declineRewards).to.equal( (await mirrorNodeClient.getAccountData(accountId)).decline_reward, ); - } + }; - it("(#1) Updates the decline reward policy of an account to decline staking rewards", async function () { + it("(#1) Updates the decline reward policy of an account to decline staking rewards", async () => { // Attempt to update the decline reward policy of the account to decline staking rewards. const declineStakingRewards = true; await JSONRPCRequest(this, "updateAccount", { @@ -1036,7 +1042,7 @@ describe("AccountUpdateTransaction", function () { ); }); - it("(#2) Updates the decline reward policy of an account to not decline staking rewards", async function () { + it("(#2) Updates the decline reward policy of an account to not decline staking rewards", async () => { // Attempt to update the decline reward policy of the account to not decline staking rewards. const declineStakingRewards = false; await JSONRPCRequest(this, "updateAccount", { diff --git a/test/token-service/test_tokenCreateTransaction.js b/src/tests/token-service/test-token-create-transaction.ts similarity index 90% rename from test/token-service/test_tokenCreateTransaction.js rename to src/tests/token-service/test-token-create-transaction.ts index cb554f1..24e6a20 100644 --- a/test/token-service/test_tokenCreateTransaction.js +++ b/src/tests/token-service/test-token-create-transaction.ts @@ -1,26 +1,27 @@ import crypto from "crypto"; import { assert, expect } from "chai"; -import { JSONRPCRequest } from "../../client.js"; -import mirrorNodeClient from "../../mirrorNodeClient.js"; -import consensusInfoClient from "../../consensusInfoClient.js"; -import { setOperator } from "../../setup_Tests.js"; +import { JSONRPCRequest } from "@services/Client"; +import mirrorNodeClient from "@services/MirrorNodeClient"; +import consensusInfoClient from "@services/ConsensusInfoClient"; -import { - twoThresholdKeyParams, - twoLevelsNestedKeyListParams, - fourKeysKeyListParams, -} from "../../utils/helpers/constants/key-list.js"; +import { setOperator } from "@helpers/setup-tests"; import { verifyTokenKey, verifyTokenKeyList, verifyTokenExpirationTimeUpdate, -} from "../../utils/helpers/verify-token-tx.js"; +} from "@helpers/verify-token-tx"; import { verifyTokenCreationWithFixedFee, verifyTokenCreationWithFractionalFee, verifyTokenCreationWithRoyaltyFee, -} from "../../utils/helpers/custom-fees.js"; +} from "@helpers/custom-fees"; + +import { + twoThresholdKeyParams, + twoLevelsNestedKeyListParams, + fourKeysKeyListParams, +} from "@constants/key-list"; /** * Tests for TokenCreateTransaction @@ -30,31 +31,33 @@ describe("TokenCreateTransaction", function () { this.timeout(30000); // Each test should first establish the network to use, and then teardown the network when complete. - beforeEach(async function () { + beforeEach(async () => { await setOperator( - process.env.OPERATOR_ACCOUNT_ID, - process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + this, + process.env.OPERATOR_ACCOUNT_ID as string, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY as string, ); }); - afterEach(async function () { + afterEach(async () => { await JSONRPCRequest(this, "reset"); }); - describe("Name", function () { - async function verifyTokenCreationWithName(tokenId, name) { + describe("Name", () => { + const verifyTokenCreationWithName = async ( + tokenId: string, + name: string, + ) => { expect(name).to.equal( - await ( - await consensusInfoClient.getTokenInfo(tokenId) - ).name, + (await consensusInfoClient.getTokenInfo(tokenId)).name, ); expect(name).to.equal( await ( await mirrorNodeClient.getTokenData(tokenId) ).name, ); - } + }; - it("(#1) Creates a token with a name that is a valid length", async function () { + it("(#1) Creates a token with a name that is a valid length", async () => { const name = "testname"; const response = await JSONRPCRequest(this, "createToken", { name: name, @@ -65,7 +68,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithName(response.tokenId, name); }); - it("(#2) Creates a token with a name that is the minimum length", async function () { + it("(#2) Creates a token with a name that is the minimum length", async () => { const name = "t"; const response = await JSONRPCRequest(this, "createToken", { name: name, @@ -76,14 +79,14 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithName(response.tokenId, name); }); - it("(#3) Creates a token with a name that is empty", async function () { + it("(#3) Creates a token with a name that is empty", async () => { try { await JSONRPCRequest(this, "createToken", { name: "", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "MISSING_TOKEN_NAME"); return; } @@ -91,7 +94,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Creates a token with a name that is the maximum length", async function () { + it("(#4) Creates a token with a name that is the maximum length", async () => { 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(this, "createToken", { @@ -103,14 +106,14 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithName(response.tokenId, name); }); - it("(#5) Creates a token with a name that exceeds the maximum length", async function () { + it("(#5) Creates a token with a name that exceeds the maximum length", async () => { try { await JSONRPCRequest(this, "createToken", { name: "This is a long name that is not valid because it exceeds 100 characters and it should fail the test!!", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_NAME_TOO_LONG"); return; } @@ -118,13 +121,13 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Creates a token with no name", async function () { + it("(#6) Creates a token with no name", async () => { try { await JSONRPCRequest(this, "createToken", { symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "MISSING_TOKEN_NAME"); return; } @@ -133,21 +136,22 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Symbol", function () { - async function verifyTokenCreationWithSymbol(tokenId, symbol) { + describe("Symbol", () => { + const verifyTokenCreationWithSymbol = async ( + tokenId: string, + symbol: string, + ) => { expect(symbol).to.equal( - await ( - await consensusInfoClient.getTokenInfo(tokenId) - ).symbol, + (await consensusInfoClient.getTokenInfo(tokenId)).symbol, ); expect(symbol).to.equal( await ( await mirrorNodeClient.getTokenData(tokenId) ).symbol, ); - } + }; - it("(#1) Creates a token with a symbol that is the minimum length", async function () { + it("(#1) Creates a token with a symbol that is the minimum length", async () => { const symbol = "t"; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -158,14 +162,14 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithSymbol(response.tokenId, symbol); }); - it("(#2) Creates a token with a symbol that is empty", async function () { + it("(#2) Creates a token with a symbol that is empty", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", symbol: "", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "MISSING_TOKEN_SYMBOL"); return; } @@ -173,7 +177,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Creates a token with a symbol that is the maximum length", async function () { + it("(#3) Creates a token with a symbol that is the maximum length", async () => { 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(this, "createToken", { @@ -185,7 +189,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithSymbol(response.tokenId, symbol); }); - it("(#4) Creates a token with a symbol that exceeds the maximum length", async function () { + it("(#4) Creates a token with a symbol that exceeds the maximum length", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -193,7 +197,7 @@ describe("TokenCreateTransaction", function () { "This is a long symbol that is not valid because it exceeds 100 characters and it should fail the test", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_SYMBOL_TOO_LONG"); return; } @@ -201,13 +205,13 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Creates a token with no symbol", async function () { + it("(#5) Creates a token with no symbol", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "MISSING_TOKEN_SYMBOL"); return; } @@ -216,20 +220,21 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Decimals", function () { - async function verifyTokenCreationWithDecimals(tokenId, decimals) { + describe("Decimals", () => { + const verifyTokenCreationWithDecimals = async ( + tokenId: string, + decimals: number, + ) => { expect(decimals).to.equal( - await ( - await consensusInfoClient.getTokenInfo(tokenId) - ).decimals, + (await consensusInfoClient.getTokenInfo(tokenId)).decimals, ); expect(decimals).to.equal( Number(await (await mirrorNodeClient.getTokenData(tokenId)).decimals), ); - } + }; - it("(#1) Creates a fungible token with 0 decimals", async function () { + it("(#1) Creates a fungible token with 0 decimals", async () => { const decimals = 0; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -241,7 +246,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithDecimals(response.tokenId, decimals); }); - it("(#2) Creates a fungible token with -1 decimals", async function () { + it("(#2) Creates a fungible token with -1 decimals", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -249,7 +254,7 @@ describe("TokenCreateTransaction", function () { decimals: -1, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); return; } @@ -257,7 +262,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Creates a fungible token with 2,147,483,647 (int32 max) decimals", async function () { + it("(#3) Creates a fungible token with 2,147,483,647 (int32 max) decimals", async () => { const decimals = 2147483647; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -269,7 +274,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithDecimals(response.tokenId, decimals); }); - it("(#4) Creates a fungible token with 2,147,483,646 (int32 max - 1) decimals", async function () { + it("(#4) Creates a fungible token with 2,147,483,646 (int32 max - 1) decimals", async () => { const decimals = 2147483646; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -281,7 +286,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithDecimals(response.tokenId, decimals); }); - it("(#5) Creates a fungible token with 2,147,483,648 (int32 max + 1) decimals", async function () { + it("(#5) Creates a fungible token with 2,147,483,648 (int32 max + 1) decimals", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -289,7 +294,7 @@ describe("TokenCreateTransaction", function () { decimals: 2147483648, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); return; } @@ -297,7 +302,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Creates a fungible token with 4,294,967,295 (uint32 max) decimals", async function () { + it("(#6) Creates a fungible token with 4,294,967,295 (uint32 max) decimals", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -305,7 +310,7 @@ describe("TokenCreateTransaction", function () { decimals: 4294967295, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); return; } @@ -313,7 +318,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Creates a fungible token with 4,294,967,294 (uint32 max - 1) decimals", async function () { + it("(#7) Creates a fungible token with 4,294,967,294 (uint32 max - 1) decimals", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -321,7 +326,7 @@ describe("TokenCreateTransaction", function () { decimals: 4294967294, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); return; } @@ -329,7 +334,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#8) Creates a fungible token with -2,147,483,648 (int32 min) decimals", async function () { + it("(#8) Creates a fungible token with -2,147,483,648 (int32 min) decimals", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -337,7 +342,7 @@ describe("TokenCreateTransaction", function () { decimals: -2147483648, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); return; } @@ -345,7 +350,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#9) Creates a fungible token with -2,147,483,647 (int32 min + 1) decimals", async function () { + it("(#9) Creates a fungible token with -2,147,483,647 (int32 min + 1) decimals", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -353,7 +358,7 @@ describe("TokenCreateTransaction", function () { decimals: -2147483647, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); return; } @@ -361,7 +366,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Creates an NFT with a decimal amount of zero", async function () { + it("(#10) Creates an NFT with a decimal amount of zero", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -381,7 +386,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithDecimals(response.tokenId, decimals); }); - it("(#11) Creates an NFT with a nonzero decimal amount", async function () { + it("(#11) Creates an NFT with a nonzero decimal amount", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -390,7 +395,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, tokenType: "nft", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_DECIMALS"); return; } @@ -399,11 +404,11 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Initial Supply", function () { - async function verifyTokenCreationWithInitialSupply( - tokenId, - initialSupply, - ) { + describe("Initial Supply", () => { + const verifyTokenCreationWithInitialSupply = async ( + tokenId: string, + initialSupply: string, + ) => { const totalSupplyConsensus = await ( await consensusInfoClient.getTokenInfo(tokenId) ).totalSupply; @@ -414,9 +419,9 @@ describe("TokenCreateTransaction", function () { expect(initialSupply).to.equal(totalSupplyConsensus.toString()); expect(initialSupply).to.equal(totalSupplyMirror); - } + }; - it("(#1) Creates a fungible token with 0 initial supply", async function () { + it("(#1) Creates a fungible token with 0 initial supply", async () => { const initialSupply = "0"; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -431,7 +436,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#2) Creates a fungible token with -1 initial supply", async function () { + it("(#2) Creates a fungible token with -1 initial supply", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -439,7 +444,7 @@ describe("TokenCreateTransaction", function () { initialSupply: "-1", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); return; } @@ -447,7 +452,7 @@ describe("TokenCreateTransaction", function () { 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 () { + it("(#3) Creates a fungible token with 9,223,372,036,854,775,807 (int64 max) initial supply", async () => { const initialSupply = "9223372036854775807"; const response = await JSONRPCRequest(this, "createToken", { @@ -463,7 +468,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#4) Creates a fungible token with 9,223,372,036,854,775,806 (int64 max - 1) initial supply", async function () { + it("(#4) Creates a fungible token with 9,223,372,036,854,775,806 (int64 max - 1) initial supply", async () => { const initialSupply = "9223372036854775806"; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -478,7 +483,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#5) Creates a fungible token with -9,223,372,036,854,775,808 (int64 min) initial supply", async function () { + it("(#5) Creates a fungible token with -9,223,372,036,854,775,808 (int64 min) initial supply", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -486,7 +491,7 @@ describe("TokenCreateTransaction", function () { initialSupply: "-9223372036854775808", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); return; } @@ -494,7 +499,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Creates a fungible token with -9,223,372,036,854,775,807 (int64 min + 1) initial supply", async function () { + it("(#6) Creates a fungible token with -9,223,372,036,854,775,807 (int64 min + 1) initial supply", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -502,7 +507,7 @@ describe("TokenCreateTransaction", function () { initialSupply: "-9223372036854775807", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); return; } @@ -510,7 +515,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Creates a fungible token with a valid initial supply and decimals", async function () { + it("(#7) Creates a fungible token with a valid initial supply and decimals", async () => { const decimals = 2; const initialSupply = "1000000"; const response = await JSONRPCRequest(this, "createToken", { @@ -527,7 +532,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#8) Creates a fungible token with a valid initial supply and more decimals", async function () { + it("(#8) Creates a fungible token with a valid initial supply and more decimals", async () => { const decimals = 6; const initialSupply = "1000000"; const response = await JSONRPCRequest(this, "createToken", { @@ -544,7 +549,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#9) Creates an NFT with an initial supply of zero", async function () { + it("(#9) Creates an NFT with an initial supply of zero", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -567,7 +572,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#10) Creates an NFT with an initial supply of zero without a supply key", async function () { + it("(#10) Creates an NFT with an initial supply of zero without a supply key", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -576,7 +581,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, tokenType: "nft", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); return; } @@ -584,7 +589,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) Creates an NFT with a nonzero initial supply", async function () { + it("(#11) Creates an NFT with a nonzero initial supply", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -593,7 +598,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, tokenType: "nft", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_INITIAL_SUPPLY"); return; } @@ -602,24 +607,24 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Treasury Account ID", function () { - async function verifyTokenCreationWithTreasuryAccount( - tokenId, - treasuryAccountId, - ) { + describe("Treasury Account ID", () => { + const verifyTokenCreationWithTreasuryAccount = async ( + tokenId: string, + treasuryAccountId: string, + ) => { expect(treasuryAccountId).to.equal( - await ( + ( await consensusInfoClient.getTokenInfo(tokenId) - ).treasuryAccountId.toString(), + ).treasuryAccountId?.toString(), ); expect(treasuryAccountId).to.equal( await ( await mirrorNodeClient.getTokenData(tokenId) ).treasury_account_id, ); - } + }; - it("(#1) Creates a token with a treasury account", async function () { + it("(#1) Creates a token with a treasury account", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -644,7 +649,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithTreasuryAccount(response.tokenId, accountId); }); - it("(#2) Creates a token with a treasury account without signing with the account's private key", async function () { + it("(#2) Creates a token with a treasury account without signing with the account's private key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -663,7 +668,7 @@ describe("TokenCreateTransaction", function () { symbol: "testsymbol", treasuryAccountId: accountId, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -672,14 +677,14 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Creates a token with a treasury account that doesn't exist", async function () { + it("(#3) Creates a token with a treasury account that doesn't exist", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: "123.456.789", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_ACCOUNT_ID"); return; } @@ -688,7 +693,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Creates a token with a treasury account that is deleted", async function () { + it("(#4) Creates a token with a treasury account that is deleted", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -718,7 +723,7 @@ describe("TokenCreateTransaction", function () { signers: [key], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TREASURY_ACCOUNT_FOR_TOKEN"); return; } @@ -728,8 +733,8 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Admin Key", function () { - it("(#1) Creates a token with a valid ED25519 public key as its admin key", async function () { + describe("Admin Key", () => { + it("(#1) Creates a token with a valid ED25519 public key as its admin key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -756,7 +761,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "adminKey"); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its admin key", async function () { + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its admin key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -783,7 +788,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "adminKey"); }); - it("(#3) Creates a token with a valid ED25519 private key as its admin key", async function () { + it("(#3) Creates a token with a valid ED25519 private key as its admin key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -810,7 +815,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "adminKey"); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its admin key", async function () { + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its admin key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -837,7 +842,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "adminKey"); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async () => { const keyList = await JSONRPCRequest( this, "generateKey", @@ -862,7 +867,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, keyList.key, "adminKey"); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its admin key", async function () { + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its admin key", async () => { const nestedKeyList = await JSONRPCRequest( this, "generateKey", @@ -889,7 +894,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, nestedKeyList.key, "adminKey"); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async function () { + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async () => { const thresholdKey = await JSONRPCRequest(this, "generateKey", { type: "thresholdKey", threshold: 2, @@ -919,7 +924,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, thresholdKey.key, "adminKey"); }); - it("(#8) Creates a token with a valid key as its admin key but doesn't sign with it", async function () { + it("(#8) Creates a token with a valid key as its admin key but doesn't sign with it", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -933,7 +938,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, adminKey: key, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -941,7 +946,7 @@ 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("(#9) Creates a token with an invalid key as its admin key", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -949,7 +954,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, adminKey: crypto.randomBytes(88).toString("hex"), }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -958,8 +963,8 @@ describe("TokenCreateTransaction", function () { }); }); - describe("KYC Key", function () { - it("(#1) Creates a token with a valid ED25519 public key as its KYC key", async function () { + describe("KYC Key", () => { + it("(#1) Creates a token with a valid ED25519 public key as its KYC key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -976,7 +981,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "kycKey"); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its KYC key", async function () { + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its KYC key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -993,7 +998,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "kycKey"); }); - it("(#3) Creates a token with a valid ED25519 private key as its KYC key", async function () { + it("(#3) Creates a token with a valid ED25519 private key as its KYC key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1017,7 +1022,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "kycKey"); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its KYC key", async function () { + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its KYC key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -1041,7 +1046,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "kycKey"); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -1060,7 +1065,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, keyList, "kycKey"); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its KYC key", async function () { + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its KYC key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -1079,7 +1084,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, nestedKeyList, "kycKey"); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "thresholdKey", threshold: 2, @@ -1108,7 +1113,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, thresholdKey, "kycKey"); }); - it("(#8) 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 () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1116,7 +1121,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, kycKey: crypto.randomBytes(88).toString("hex"), }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -1126,8 +1131,8 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Freeze Key", function () { - it("(#1) Creates a token with a valid ED25519 public key as its freeze key", async function () { + describe("Freeze Key", () => { + it("(#1) Creates a token with a valid ED25519 public key as its freeze key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -1144,7 +1149,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "freezeKey"); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its freeze key", async function () { + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its freeze key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -1161,7 +1166,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "freezeKey"); }); - it("(#3) Creates a token with a valid ED25519 private key as its freeze key", async function () { + it("(#3) Creates a token with a valid ED25519 private key as its freeze key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1185,7 +1190,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "freezeKey"); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its freeze key", async function () { + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its freeze key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -1209,7 +1214,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "freezeKey"); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -1228,7 +1233,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, keyList, "freezeKey"); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its freeze key", async function () { + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its freeze key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -1247,7 +1252,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, nestedKeyList, "freezeKey"); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "thresholdKey", threshold: 2, @@ -1276,7 +1281,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, thresholdKey, "freezeKey"); }); - it("(#8) 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 () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1284,7 +1289,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeKey: crypto.randomBytes(88).toString("hex"), }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -1293,8 +1298,8 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Wipe Key", function () { - it("(#1) Creates a token with a valid ED25519 public key as its wipe key", async function () { + describe("Wipe Key", () => { + it("(#1) Creates a token with a valid ED25519 public key as its wipe key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -1311,7 +1316,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "wipeKey"); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its wipe key", async function () { + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its wipe key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -1328,7 +1333,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "wipeKey"); }); - it("(#3) Creates a token with a valid ED25519 private key as its wipe key", async function () { + it("(#3) Creates a token with a valid ED25519 private key as its wipe key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1352,7 +1357,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "wipeKey"); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its wipe key", async function () { + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its wipe key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -1376,7 +1381,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "wipeKey"); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -1395,7 +1400,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, keyList, "wipeKey"); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its wipe key", async function () { + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its wipe key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -1414,7 +1419,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, nestedKeyList, "wipeKey"); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "thresholdKey", threshold: 2, @@ -1443,7 +1448,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, thresholdKey, "wipeKey"); }); - it("(#8) 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 () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1451,7 +1456,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, wipeKey: crypto.randomBytes(88).toString("hex"), }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -1460,8 +1465,8 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Supply Key", function () { - it("(#1) Creates a token with a valid ED25519 public key as its supply key", async function () { + describe("Supply Key", () => { + it("(#1) Creates a token with a valid ED25519 public key as its supply key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -1478,7 +1483,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "supplyKey"); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its supply key", async function () { + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its supply key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -1495,7 +1500,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "supplyKey"); }); - it("(#3) Creates a token with a valid ED25519 private key as its supply key", async function () { + it("(#3) Creates a token with a valid ED25519 private key as its supply key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1519,7 +1524,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "supplyKey"); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its supply key", async function () { + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its supply key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -1543,7 +1548,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "supplyKey"); }); - 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) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -1562,7 +1567,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, keyList, "supplyKey"); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its supply key", async function () { + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its supply key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -1581,7 +1586,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, nestedKeyList, "supplyKey"); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "thresholdKey", threshold: 2, @@ -1610,7 +1615,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, thresholdKey, "supplyKey"); }); - it("(#8) 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 () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1618,7 +1623,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, supplyKey: crypto.randomBytes(88).toString("hex"), }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -1627,11 +1632,11 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Freeze Default", function () { - async function verifyTokenCreationWithFreezeDefault( - tokenId, - freezeDefault, - ) { + describe("Freeze Default", () => { + const verifyTokenCreationWithFreezeDefault = async ( + tokenId: string, + freezeDefault: boolean, + ) => { expect(freezeDefault).to.equal( await ( await consensusInfoClient.getTokenInfo(tokenId) @@ -1643,9 +1648,9 @@ describe("TokenCreateTransaction", function () { await mirrorNodeClient.getTokenData(tokenId) ).freeze_default, ); - } + }; - it("(#1) Creates a token with a frozen default status", async function () { + it("(#1) Creates a token with a frozen default status", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1667,7 +1672,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#2) Creates a token with a frozen default status and no freeze key", async function () { + it("(#2) Creates a token with a frozen default status and no freeze key", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1675,7 +1680,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, freezeDefault: true, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_HAS_NO_FREEZE_KEY"); return; } @@ -1683,7 +1688,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Creates a token with an unfrozen default status", async function () { + it("(#3) Creates a token with an unfrozen default status", async () => { const responseKey = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1706,8 +1711,8 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Expiration Time", function () { - it("(#1) Creates a token with an expiration time of 0 seconds", async function () { + describe("Expiration Time", () => { + it("(#1) Creates a token with an expiration time of 0 seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1715,7 +1720,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, expirationTime: "0", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -1723,7 +1728,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Creates a token with an expiration time of -1 seconds", async function () { + it("(#2) Creates a token with an expiration time of -1 seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1731,7 +1736,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, expirationTime: "-1", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -1739,7 +1744,7 @@ describe("TokenCreateTransaction", function () { 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("(#3) Creates a token with an expiration time of 9,223,372,036,854,775,807 (int64 max) seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1747,7 +1752,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, expirationTime: "9223372036854775807", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -1755,7 +1760,7 @@ describe("TokenCreateTransaction", function () { 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 () { + it("(#4) Creates a token with an expiration time of 9,223,372,036,854,775,806 (int64 max - 1) seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1763,7 +1768,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, expirationTime: "9223372036854775806", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -1771,7 +1776,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Creates a token with an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + it.skip("(#5) Creates a token with an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1779,7 +1784,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, expirationTime: "-9223372036854775808", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -1787,7 +1792,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Creates a token with an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds", async function () { + it("(#6) Creates a token with an expiration time of -9,223,372,036,854,775,807 (int64 min + 1) seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1795,14 +1800,14 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, expirationTime: "-9223372036854775807", }); - } catch (err) { + } catch (err: any) { 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 60 days (5,184,000 seconds) from the current time", async function () { + it("(#7) Creates a token with an expiration time of 60 days (5,184,000 seconds) from the current time", async () => { const expirationTime = ( Math.floor(Date.now() / 1000) + 5184000 ).toString(); @@ -1815,7 +1820,7 @@ describe("TokenCreateTransaction", function () { }); }); - it("(#8) Creates a token with an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { + it("(#8) Creates a token with an expiration time of 30 days (2,592,000 seconds) from the current time", async () => { const expirationTime = ( Math.floor(Date.now() / 1000) + 2592000 ).toString(); @@ -1830,20 +1835,19 @@ describe("TokenCreateTransaction", function () { await verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); }); - it.skip("(#9) Creates a token with an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async function () { + it.skip("(#9) Creates a token with an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async () => { const expirationTime = ( Math.floor(Date.now() / 1000) + 2591999 ).toString(); try { - const response = await JSONRPCRequest(this, "createToken", { + await JSONRPCRequest(this, "createToken", { name: "testname", symbol: "testsymbol", treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, expirationTime, }); - if (response.status === "NOT_IMPLEMENTED") this.skip(); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -1851,7 +1855,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Creates a token with an expiration time of 8,000,001 seconds from the current time", async function () { + it("(#10) Creates a token with an expiration time of 8,000,001 seconds from the current time", async () => { const expirationTime = ( Math.floor(Date.now() / 1000) + 8000001 ).toString(); @@ -1866,7 +1870,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); }); - it("(#11) Creates a token with an expiration time of 8,000,002 seconds from the current time", async function () { + it("(#11) Creates a token with an expiration time of 8,000,002 seconds from the current time", async () => { try { const expirationTime = ( Math.floor(Date.now() / 1000) + 8000002 @@ -1879,7 +1883,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, expirationTime: expirationTime, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -1888,8 +1892,8 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Auto Renew Account ID", function () { - it("(#1) Creates a token with an auto renew account", async function () { + describe("Auto Renew Account ID", () => { + it("(#1) Creates a token with an auto renew account", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1915,9 +1919,9 @@ describe("TokenCreateTransaction", function () { const tokenId = response.tokenId; expect(accountId).to.equal( - await ( + ( await consensusInfoClient.getTokenInfo(tokenId) - ).autoRenewAccountId.toString(), + ).autoRenewAccountId?.toString(), ); expect(accountId).to.equal( await ( @@ -1926,7 +1930,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#2) Creates a token with an auto renew account without signing with the account's key", async function () { + it("(#2) Creates a token with an auto renew account without signing with the account's key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1947,7 +1951,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewAccountId: accountId, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -1956,7 +1960,7 @@ describe("TokenCreateTransaction", function () { }; }); - it("(#3) Creates a token with an auto renew account that doesn't exist", async function () { + it("(#3) Creates a token with an auto renew account that doesn't exist", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1964,7 +1968,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewAccountId: "123.456.789", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); return; } @@ -1972,7 +1976,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Creates a token with the auto renew account not set", async function () { + it("(#4) Creates a token with the auto renew account not set", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -1980,7 +1984,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewAccountId: "", }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -1989,7 +1993,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -2020,7 +2024,7 @@ describe("TokenCreateTransaction", function () { signers: [key], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); return; } @@ -2030,15 +2034,15 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Auto Renew Period", function () { - async function verifyTokenCreationWithAutoRenewPeriod( - tokenId, - autoRenewPeriod, - ) { + describe("Auto Renew Period", () => { + const verifyTokenCreationWithAutoRenewPeriod = async ( + tokenId: string, + autoRenewPeriod: string, + ) => { expect(autoRenewPeriod).to.equal( - await ( + ( await consensusInfoClient.getTokenInfo(tokenId) - ).autoRenewPeriod.seconds.toString(), + ).autoRenewPeriod?.seconds.toString(), ); expect(autoRenewPeriod).to.equal( @@ -2046,9 +2050,9 @@ describe("TokenCreateTransaction", function () { await mirrorNodeClient.getTokenData(tokenId) ).auto_renew_period.toString(), ); - } + }; - it("(#1) Creates a token with an auto renew period set to 0 seconds", async function () { + it("(#1) Creates a token with an auto renew period set to 0 seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2057,7 +2061,7 @@ describe("TokenCreateTransaction", function () { autoRenewAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: "0", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2065,7 +2069,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Creates a token with an auto renew period set to -1 seconds", async function () { + it("(#2) Creates a token with an auto renew period set to -1 seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2074,7 +2078,7 @@ describe("TokenCreateTransaction", function () { autoRenewAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: "-1", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2082,7 +2086,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Creates a token with an auto renew period of 9,223,372,036,854,775,807 (`int64` max) seconds", async function () { + it("(#3) Creates a token with an auto renew period of 9,223,372,036,854,775,807 (`int64` max) seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2090,7 +2094,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: "9223372036854775807", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2098,7 +2102,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Creates a token with an auto renew period of 9,223,372,036,854,775,806 (`int64` max - 1) seconds", async function () { + it("(#4) Creates a token with an auto renew period of 9,223,372,036,854,775,806 (`int64` max - 1) seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2106,7 +2110,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: "9223372036854775806", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2114,7 +2118,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#5) Creates a token with an auto renew period of -9,223,372,036,854,775,808 (`int64` min) seconds", async function () { + it.skip("(#5) Creates a token with an auto renew period of -9,223,372,036,854,775,808 (`int64` min) seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2122,7 +2126,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: "-9223372036854775808", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2130,7 +2134,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Creates a token with an auto renew period of -9,223,372,036,854,775,807 (`int64` min + 1) seconds", async function () { + it("(#6) Creates a token with an auto renew period of -9,223,372,036,854,775,807 (`int64` min + 1) seconds", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2138,7 +2142,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: "-9223372036854775807", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2146,7 +2150,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Creates a token with an auto renew period of 60 days (5,184,000 seconds)", async function () { + it("(#7) Creates a token with an auto renew period of 60 days (5,184,000 seconds)", async () => { const autoRenewPeriod = "5184000"; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2162,7 +2166,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#8) Creates a token with an auto renew period of 30 days (2,592,000 seconds)", async function () { + it("(#8) Creates a token with an auto renew period of 30 days (2,592,000 seconds)", async () => { const autoRenewPeriod = "2592000"; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2178,7 +2182,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#9) Creates a token with an auto renew period of 30 days minus one second (2,591,999 seconds)", async function () { + it("(#9) Creates a token with an auto renew period of 30 days minus one second (2,591,999 seconds)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2187,7 +2191,7 @@ describe("TokenCreateTransaction", function () { autoRenewAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: "2591999", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2195,7 +2199,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Creates a token with an auto renew period set to the maximum period of 8,000,001 seconds", async function () { + it("(#10) Creates a token with an auto renew period set to the maximum period of 8,000,001 seconds", async () => { const autoRenewPeriod = "8000001"; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2211,7 +2215,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#11) Creates a token with an auto renew period set to the maximum period plus one second (8,000,002 seconds)", async function () { + it("(#11) Creates a token with an auto renew period set to the maximum period plus one second (8,000,002 seconds)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2220,7 +2224,7 @@ describe("TokenCreateTransaction", function () { autoRenewAccountId: process.env.OPERATOR_ACCOUNT_ID, autoRenewPeriod: "8000002", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2229,21 +2233,22 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Memo", function () { - async function verifyTokenCreationWithMemo(tokenId, memo) { + describe("Memo", () => { + const verifyTokenCreationWithMemo = async ( + tokenId: string, + memo: string, + ) => { expect(memo).to.equal( - await ( - await consensusInfoClient.getTokenInfo(tokenId) - ).tokenMemo, + (await consensusInfoClient.getTokenInfo(tokenId)).tokenMemo, ); expect(memo).to.equal( await ( await mirrorNodeClient.getTokenData(tokenId) ).memo, ); - } + }; - it("(#1) Creates a token with a memo that is a valid length", async function () { + it("(#1) Creates a token with a memo that is a valid length", async () => { const memo = "testmemo"; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2255,7 +2260,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithMemo(response.tokenId, memo); }); - it("(#2) Creates a token with a memo that is the minimum length", async function () { + it("(#2) Creates a token with a memo that is the minimum length", async () => { const memo = ""; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2267,7 +2272,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithMemo(response.tokenId, memo); }); - it("(#3) Creates a token with a memo that is the maximum length", async function () { + it("(#3) Creates a token with a memo that is the maximum length", async () => { 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(this, "createToken", { @@ -2280,7 +2285,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithMemo(response.tokenId, memo); }); - it("(#4) Creates a token with a memo that exceeds the maximum length", async function () { + it("(#4) Creates a token with a memo that exceeds the maximum length", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2288,7 +2293,7 @@ describe("TokenCreateTransaction", function () { 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!!", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "MEMO_TOO_LONG"); return; } @@ -2297,12 +2302,13 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Token Type", function () { - async function verifyTokenCreationWithTokenType(tokenId, type) { + describe("Token Type", () => { + const verifyTokenCreationWithTokenType = async ( + tokenId: string, + type: string, + ) => { expect(type).to.deep.equal( - await ( - await consensusInfoClient.getTokenInfo(tokenId) - ).tokenType.toString(), + (await consensusInfoClient.getTokenInfo(tokenId)).tokenType?.toString(), ); expect(type).to.equal( @@ -2310,9 +2316,9 @@ describe("TokenCreateTransaction", function () { await mirrorNodeClient.getTokenData(tokenId) ).type, ); - } + }; - it("(#1) Creates a fungible token", async function () { + it("(#1) Creates a fungible token", async () => { const response = await JSONRPCRequest(this, "createToken", { name: "testname", symbol: "testsymbol", @@ -2326,7 +2332,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#2) Creates an NFT", async function () { + it("(#2) Creates an NFT", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -2348,21 +2354,24 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Supply Type", function () { - async function verifyTokenCreationWithSupplyType(tokenId, type) { + describe("Supply Type", () => { + const verifyTokenCreationWithSupplyType = async ( + tokenId: string, + type: string, + ) => { expect(type).to.equal( - await ( + ( await consensusInfoClient.getTokenInfo(tokenId) - ).supplyType.toString(), + ).supplyType?.toString(), ); expect(type).to.equal( await ( await mirrorNodeClient.getTokenData(tokenId) ).supply_type, ); - } + }; - it("(#1) Creates a token with a finite supply", async function () { + it("(#1) Creates a token with a finite supply", async () => { const response = await JSONRPCRequest(this, "createToken", { name: "testname", symbol: "testsymbol", @@ -2374,7 +2383,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithSupplyType(response.tokenId, "FINITE"); }); - it("(#2) Creates a token with an infinite supply", async function () { + it("(#2) Creates a token with an infinite supply", async () => { const response = await JSONRPCRequest(this, "createToken", { name: "testname", symbol: "testsymbol", @@ -2386,9 +2395,12 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Max Supply", function () { - async function verifyTokenCreationWithMaxSupply(tokenId, maxSupply) { - const totalMaxSupplyConsensus = await ( + describe("Max Supply", () => { + const verifyTokenCreationWithMaxSupply = async ( + tokenId: string, + maxSupply: string, + ) => { + const totalMaxSupplyConsensus = ( await consensusInfoClient.getTokenInfo(tokenId) ).maxSupply; @@ -2396,11 +2408,11 @@ describe("TokenCreateTransaction", function () { await mirrorNodeClient.getTokenData(tokenId) ).max_supply; - expect(maxSupply).to.equal(totalMaxSupplyConsensus.toString()); + expect(maxSupply).to.equal(totalMaxSupplyConsensus?.toString()); expect(maxSupply).to.equal(totalMaxSupplyMirror); - } + }; - it("(#1) Creates a token with 0 max supply", async function () { + it("(#1) Creates a token with 0 max supply", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2409,7 +2421,7 @@ describe("TokenCreateTransaction", function () { supplyType: "finite", maxSupply: "0", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); return; } @@ -2417,7 +2429,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Creates a token with -1 max supply", async function () { + it("(#2) Creates a token with -1 max supply", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2426,7 +2438,7 @@ describe("TokenCreateTransaction", function () { supplyType: "finite", maxSupply: "-1", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); return; } @@ -2434,7 +2446,7 @@ describe("TokenCreateTransaction", function () { 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 () { + it("(#3) Creates a token with 9,223,372,036,854,775,807 (int64 max) max supply", async () => { const maxSupply = "9223372036854775807"; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2447,7 +2459,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); }); - it("(#4) Creates a token with 9,223,372,036,854,775,806 (int64 max - 1) max supply", async function () { + it("(#4) Creates a token with 9,223,372,036,854,775,806 (int64 max - 1) max supply", async () => { const maxSupply = "9223372036854775806"; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2460,7 +2472,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithMaxSupply(response.tokenId, maxSupply); }); - it("(#5) Creates a token with -9,223,372,036,854,775,808 (int64 min) max supply", async function () { + it("(#5) Creates a token with -9,223,372,036,854,775,808 (int64 min) max supply", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2469,7 +2481,7 @@ describe("TokenCreateTransaction", function () { supplyType: "finite", maxSupply: "-9223372036854775808", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); return; } @@ -2477,7 +2489,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Creates a token with -9,223,372,036,854,775,807 (int64 min) max supply", async function () { + it("(#6) Creates a token with -9,223,372,036,854,775,807 (int64 min) max supply", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2486,7 +2498,7 @@ describe("TokenCreateTransaction", function () { supplyType: "finite", maxSupply: "-9223372036854775807", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); return; } @@ -2494,7 +2506,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Creates a token with a max supply and an infinite supply type", async function () { + it("(#7) Creates a token with a max supply and an infinite supply type", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2503,7 +2515,7 @@ describe("TokenCreateTransaction", function () { supplyType: "infinite", maxSupply: "1000000", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_MAX_SUPPLY"); return; } @@ -2512,8 +2524,8 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Fee Schedule Key", function () { - it("(#1) Creates a token with a valid ED25519 public key as its fee schedule key", async function () { + describe("Fee Schedule Key", () => { + it("(#1) Creates a token with a valid ED25519 public key as its fee schedule key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -2530,7 +2542,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "feeScheduleKey"); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its fee schedule key", async function () { + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its fee schedule key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -2547,7 +2559,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "feeScheduleKey"); }); - it("(#3) Creates a token with a valid ED25519 private key as its fee schedule key", async function () { + it("(#3) Creates a token with a valid ED25519 private key as its fee schedule key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -2571,7 +2583,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "feeScheduleKey"); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its fee schedule key", async function () { + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its fee schedule key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -2595,7 +2607,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "feeScheduleKey"); }); - 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) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -2614,7 +2626,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, keyList, "feeScheduleKey"); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its fee schedule key", async function () { + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its fee schedule key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -2637,7 +2649,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async function () { + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "thresholdKey", threshold: 2, @@ -2670,7 +2682,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#8) 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 () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2678,7 +2690,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, feeScheduleKey: crypto.randomBytes(88).toString("hex"), }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -2687,8 +2699,8 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Custom Fees", function () { - it("(#1) Creates a token with a fixed fee with an amount of 0", async function () { + describe("Custom Fees", () => { + it("(#1) Creates a token with a fixed fee with an amount of 0", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2704,7 +2716,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -2712,7 +2724,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Creates a token with a fixed fee with an amount of -1", async function () { + it("(#2) Creates a token with a fixed fee with an amount of -1", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2728,7 +2740,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -2736,8 +2748,8 @@ describe("TokenCreateTransaction", function () { 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; + it.skip("(#3) Creates a token with a fixed fee with an amount of 9,223,372,036,854,775,807 (int64 max)", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const amount = "9223372036854775807"; const response = await JSONRPCRequest(this, "createToken", { @@ -2763,8 +2775,8 @@ describe("TokenCreateTransaction", function () { ); }); - 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; + it.skip("(#4) Creates a token with a fixed fee with an amount of 9,223,372,036,854,775,806 (int64 max - 1)", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const amount = "9223372036854775806"; const response = await JSONRPCRequest(this, "createToken", { @@ -2790,7 +2802,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#5) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + it("(#5) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,808 (int64 min)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2806,7 +2818,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -2814,7 +2826,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + it("(#6) Creates a token with a fixed fee with an amount of -9,223,372,036,854,775,807 (int64 min + 1)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2830,7 +2842,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -2838,7 +2850,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Creates a token with a fractional fee with a numerator of 0", async function () { + it("(#7) Creates a token with a fractional fee with a numerator of 0", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2858,7 +2870,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -2866,7 +2878,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#8) Creates a token with a fractional fee with a numerator of -1", async function () { + it("(#8) Creates a token with a fractional fee with a numerator of -1", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2886,7 +2898,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -2894,8 +2906,8 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#9) 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; + it.skip("(#9) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,807 (int64 max)", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "9223372036854775807"; const denominator = "10"; @@ -2933,8 +2945,8 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#10) 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; + it.skip("(#10) Creates a token with a fractional fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "9223372036854775806"; const denominator = "10"; @@ -2972,7 +2984,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#11) Creates a token with a fractional fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async function () { + it("(#11) Creates a token with a fractional fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -2992,7 +3004,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3000,7 +3012,7 @@ describe("TokenCreateTransaction", function () { 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 min + 1)", async function () { + it("(#12) Creates a token with a fractional fee with a numerator of -9,223,372,036,854,775,807 (int64 min + 1)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3020,7 +3032,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3028,7 +3040,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#13) Creates a token with a fractional fee with a denominator of 0", async function () { + it("(#13) Creates a token with a fractional fee with a denominator of 0", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3048,7 +3060,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "FRACTION_DIVIDES_BY_ZERO"); return; } @@ -3056,7 +3068,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#14) Creates a token with a fractional fee with a denominator of -1", async function () { + it("(#14) Creates a token with a fractional fee with a denominator of -1", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3076,7 +3088,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3084,8 +3096,8 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#15) 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; + it.skip("(#15) Creates a token with a fractional fee with a denominator of 9,223,372,036,854,775,807 (int64 max)", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "1"; const denominator = "9223372036854775807"; @@ -3123,8 +3135,8 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#16) 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; + it.skip("(#16) Creates a token with a fractional fee with a denominator of 9,223,372,036,854,775,806 (int64 max - 1)", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "1"; const denominator = "9223372036854775806"; @@ -3162,7 +3174,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#17) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async function () { + it("(#17) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3182,7 +3194,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3190,7 +3202,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#18) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + it("(#18) Creates a token with a fractional fee with a denominator of -9,223,372,036,854,775,807 (int64 min + 1)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3210,7 +3222,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3218,8 +3230,8 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#19) Creates a token with a fractional fee with a minimum amount of 0", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + it.skip("(#19) Creates a token with a fractional fee with a minimum amount of 0", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "1"; const denominator = "10"; @@ -3257,7 +3269,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#20) Creates a token with a fractional fee with a minimum amount of -1", async function () { + it("(#20) Creates a token with a fractional fee with a minimum amount of -1", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3277,7 +3289,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3285,7 +3297,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#21) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,807 (int64 max)", async function () { + it("(#21) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,807 (int64 max)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3305,7 +3317,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal( err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT", @@ -3316,7 +3328,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#22) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + it("(#22) Creates a token with a fractional fee with a minimum amount of 9,223,372,036,854,775,806 (int64 max - 1)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3336,7 +3348,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal( err.data.status, "FRACTIONAL_FEE_MAX_AMOUNT_LESS_THAN_MIN_AMOUNT", @@ -3347,7 +3359,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#23) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + it("(#23) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,808 (int64 min)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3367,7 +3379,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3375,7 +3387,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#24) 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("(#24) Creates a token with a fractional fee with a minimum amount of -9,223,372,036,854,775,807 (int64 min + 1)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3395,7 +3407,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3403,8 +3415,8 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#25) Creates a token with a fractional fee with a maximum amount of 0", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + it.skip("(#25) Creates a token with a fractional fee with a maximum amount of 0", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "1"; const denominator = "10"; @@ -3442,7 +3454,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#26) Creates a token with a fractional fee with a maximum amount of -1", async function () { + it("(#26) Creates a token with a fractional fee with a maximum amount of -1", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3462,7 +3474,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3470,8 +3482,8 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#27) 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; + it.skip("(#27) Creates a token with a fractional fee with a maximum amount of 9,223,372,036,854,775,807 (int64 max)", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "1"; const denominator = "10"; @@ -3509,8 +3521,8 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#28) 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; + it.skip("(#28) Creates a token with a fractional fee with a maximum amount of 9,223,372,036,854,775,806 (int64 max - 1)", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "1"; const denominator = "10"; @@ -3548,7 +3560,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#29) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,808 (int64 min)", async function () { + it("(#29) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,808 (int64 min)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3568,7 +3580,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3576,7 +3588,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#30) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + it("(#30) Creates a token with a fractional fee with a maximum amount of -9,223,372,036,854,775,807 (int64 min + 1)", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -3596,7 +3608,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3604,7 +3616,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#31) Creates a token with a royalty fee with a numerator of 0", async function () { + it("(#31) Creates a token with a royalty fee with a numerator of 0", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -3632,7 +3644,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3640,7 +3652,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#32) Creates a token with a royalty fee with a numerator of -1", async function () { + it("(#32) Creates a token with a royalty fee with a numerator of -1", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -3668,7 +3680,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3676,7 +3688,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#33) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,807 (int64 max)", async function () { + it("(#33) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,807 (int64 max)", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -3704,7 +3716,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "ROYALTY_FRACTION_CANNOT_EXCEED_ONE"); return; } @@ -3712,7 +3724,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#34) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + it("(#34) Creates a token with a royalty fee with a numerator of 9,223,372,036,854,775,806 (int64 max - 1)", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -3740,7 +3752,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "ROYALTY_FRACTION_CANNOT_EXCEED_ONE"); return; } @@ -3748,7 +3760,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#35) Creates a token with a royalty fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async function () { + it.skip("(#35) Creates a token with a royalty fee with a numerator of -9,223,372,036,854,775,808 (int64 min)", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -3776,7 +3788,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3784,7 +3796,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#36) Creates a token with a royalty fee with a numerator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + it("(#36) Creates a token with a royalty fee with a numerator of -9,223,372,036,854,775,807 (int64 min + 1)", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -3812,7 +3824,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3820,7 +3832,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#37) Creates a token with a royalty fee with a denominator of 0", async function () { + it("(#37) Creates a token with a royalty fee with a denominator of 0", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -3848,7 +3860,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "FRACTION_DIVIDES_BY_ZERO"); return; } @@ -3856,7 +3868,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#38) Creates a token with a royalty fee with a denominator of -1", async function () { + it("(#38) Creates a token with a royalty fee with a denominator of -1", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -3884,7 +3896,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -3892,14 +3904,14 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#39) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,807 (int64 max)", async function () { + it.skip("(#39) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,807 (int64 max)", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); const key = response.key; - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "1"; const denominator = "9223372036854775807"; @@ -3931,20 +3943,18 @@ describe("TokenCreateTransaction", function () { feeCollectorsExempt, numerator, denominator, - feeCollectorAccountId, - feeCollectorsExempt, fallbackFeeAmount, ); }); - it("(#40) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,806 (int64 max - 1)", async function () { + it.skip("(#40) Creates a token with a royalty fee with a denominator of 9,223,372,036,854,775,806 (int64 max - 1)", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); const key = response.key; - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "1"; const denominator = "9223372036854775806"; @@ -3976,13 +3986,11 @@ describe("TokenCreateTransaction", function () { feeCollectorsExempt, numerator, denominator, - feeCollectorAccountId, - feeCollectorsExempt, fallbackFeeAmount, ); }); - it.skip("(#41) Creates a token with a royalty fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async function () { + it.skip("(#41) Creates a token with a royalty fee with a denominator of -9,223,372,036,854,775,808 (int64 min)", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -4010,7 +4018,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -4018,7 +4026,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#42) Creates a token with a royalty fee with a denominator of -9,223,372,036,854,775,807 (int64 min + 1)", async function () { + it("(#42) Creates a token with a royalty fee with a denominator of -9,223,372,036,854,775,807 (int64 min + 1)", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -4046,7 +4054,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -4054,7 +4062,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#43) Creates a token with a royalty fee with a fallback fee with an amount of 0", async function () { + it("(#43) Creates a token with a royalty fee with a fallback fee with an amount of 0", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -4082,7 +4090,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -4090,7 +4098,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#44) Creates a token with a royalty fee with a fallback fee with an amount of -1", async function () { + it("(#44) Creates a token with a royalty fee with a fallback fee with an amount of -1", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -4118,7 +4126,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -4126,14 +4134,14 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#45) 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 () { + it.skip("(#45) 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); const key = response.key; - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "1"; const denominator = "10"; @@ -4165,20 +4173,18 @@ describe("TokenCreateTransaction", function () { feeCollectorsExempt, numerator, denominator, - feeCollectorAccountId, - feeCollectorsExempt, fallbackFeeAmount, ); }); - it("(#46) 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 () { + it.skip("(#46) 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); const key = response.key; - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "1"; const denominator = "10"; @@ -4210,13 +4216,11 @@ describe("TokenCreateTransaction", function () { feeCollectorsExempt, numerator, denominator, - feeCollectorAccountId, - feeCollectorsExempt, fallbackFeeAmount, ); }); - it.skip("(#47) 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 () { + it.skip("(#47) 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -4244,7 +4248,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -4252,7 +4256,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#48) 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 () { + it("(#48) 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -4280,7 +4284,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEE_MUST_BE_POSITIVE"); return; } @@ -4288,7 +4292,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#49) Creates a token with a fixed fee with a fee collector account that doesn't exist", async function () { + it("(#49) Creates a token with a fixed fee with a fee collector account that doesn't exist", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -4304,7 +4308,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); return; } @@ -4312,7 +4316,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#50) Creates a token with a fractional with a fee collector account that doesn't exist", async function () { + it("(#50) Creates a token with a fractional with a fee collector account that doesn't exist", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -4332,7 +4336,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); return; } @@ -4340,7 +4344,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#51) Creates a token with a royalty fee with a fee collector account that doesn't exist", async function () { + it("(#51) Creates a token with a royalty fee with a fee collector account that doesn't exist", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -4368,7 +4372,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); return; } @@ -4376,7 +4380,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#52) Creates a token with a fixed fee with an empty fee collector account", async function () { + it("(#52) Creates a token with a fixed fee with an empty fee collector account", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -4392,7 +4396,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603); return; } @@ -4400,7 +4404,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#53) Creates a token with a fractional with an empty fee collector account", async function () { + it("(#53) Creates a token with a fractional with an empty fee collector account", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -4420,7 +4424,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603); return; } @@ -4428,7 +4432,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#54) Creates a token with a royalty fee with an empty fee collector account", async function () { + it("(#54) Creates a token with a royalty fee with an empty fee collector account", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -4456,7 +4460,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603); return; } @@ -4464,7 +4468,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#55) Creates a token with a fixed fee with a deleted fee collector account", async function () { + it.skip("(#55) Creates a token with a fixed fee with a deleted fee collector account", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -4503,7 +4507,7 @@ describe("TokenCreateTransaction", function () { signers: [key], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); return; } @@ -4511,7 +4515,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#56) Creates a token with a fractional fee with a deleted fee collector account", async function () { + it.skip("(#56) Creates a token with a fractional fee with a deleted fee collector account", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -4554,7 +4558,7 @@ describe("TokenCreateTransaction", function () { signers: [key], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); return; } @@ -4562,7 +4566,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#57) Creates a token with a royalty fee with a deleted fee collector account", async function () { + it.skip("(#57) Creates a token with a royalty fee with a deleted fee collector account", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -4607,7 +4611,7 @@ describe("TokenCreateTransaction", function () { signers: [key], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_CUSTOM_FEE_COLLECTOR"); return; } @@ -4615,8 +4619,8 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#58) Creates a token with a fixed fee that is assessed with the created token", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + it("(#58) Creates a token with a fixed fee that is assessed with the created token", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const fixedFeeAmount = "10"; const denominatingTokenId = "0.0.0"; @@ -4644,7 +4648,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#59) Creates a token with a fixed fee that is assessed with a token that doesn't exist", async function () { + it("(#59) Creates a token with a fixed fee that is assessed with a token that doesn't exist", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -4661,7 +4665,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); return; } @@ -4669,7 +4673,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#60) Creates a token with a fixed fee that is assessed with an empty token", async function () { + it("(#60) Creates a token with a fixed fee that is assessed with an empty token", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -4686,7 +4690,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603); return; } @@ -4694,7 +4698,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#61) Creates a token with a fixed fee that is assessed with a deleted token", async function () { + it.skip("(#61) Creates a token with a fixed fee that is assessed with a deleted token", async () => { let response = await JSONRPCRequest(this, "createToken", { name: "testname", symbol: "testsymbol", @@ -4724,7 +4728,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_ID_IN_CUSTOM_FEES"); return; } @@ -4732,8 +4736,8 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#62) Creates a token with a fractional fee that is assessed to the receiver", async function () { - const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID; + it.skip("(#62) Creates a token with a fractional fee that is assessed to the receiver", async () => { + const feeCollectorAccountId = process.env.OPERATOR_ACCOUNT_ID as string; const feeCollectorsExempt = false; const numerator = "1"; const denominator = "10"; @@ -4771,7 +4775,7 @@ describe("TokenCreateTransaction", function () { ); }); - it("(#63) Creates a fungible token with a royalty fee", async function () { + it("(#63) Creates a fungible token with a royalty fee", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -4793,7 +4797,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal( err.data.status, "CUSTOM_ROYALTY_FEE_ONLY_ALLOWED_FOR_NON_FUNGIBLE_UNIQUE", @@ -4804,7 +4808,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#64) Creates an NFT with a fractional fee", async function () { + it("(#64) Creates an NFT with a fractional fee", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -4832,7 +4836,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal( err.data.status, "CUSTOM_FRACTIONAL_FEE_ONLY_ALLOWED_FOR_FUNGIBLE_COMMON", @@ -4843,7 +4847,7 @@ describe("TokenCreateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#65) Creates a token with more than the maximum amount of fees allowed", async function () { + it("(#65) Creates a token with more than the maximum amount of fees allowed", async () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -4929,7 +4933,7 @@ describe("TokenCreateTransaction", function () { }, ], }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "CUSTOM_FEES_LIST_TOO_LONG"); return; } @@ -4938,8 +4942,8 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Pause Key", function () { - it("(#1) Creates a token with a valid ED25519 public key as its pause key", async function () { + describe("Pause Key", () => { + it("(#1) Creates a token with a valid ED25519 public key as its pause key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -4956,7 +4960,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "pauseKey"); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its pause key", async function () { + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its pause key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -4973,7 +4977,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "pauseKey"); }); - it("(#3) Creates a token with a valid ED25519 private key as its pause key", async function () { + it("(#3) Creates a token with a valid ED25519 private key as its pause key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -4997,7 +5001,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "pauseKey"); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its pause key", async function () { + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its pause key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -5021,7 +5025,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "pauseKey"); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -5040,7 +5044,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, keyList, "pauseKey"); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its pause key", async function () { + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its pause key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -5059,7 +5063,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, nestedKeyList, "pauseKey"); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -5078,7 +5082,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, thresholdKey, "pauseKey"); }); - it("(#8) 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 () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -5086,7 +5090,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, pauseKey: crypto.randomBytes(88).toString("hex"), }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -5095,13 +5099,16 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Metadata", function () { - async function verifyTokenCreationWithMetadata(tokenId, expectedMetadata) { - const metadataConsensus = await ( + describe("Metadata", () => { + const verifyTokenCreationWithMetadata = async ( + tokenId: string, + expectedMetadata: string, + ) => { + const metadataConsensus = ( await consensusInfoClient.getTokenInfo(tokenId) ).metadata; - expect(metadataConsensus.toString("utf8")).to.equal(expectedMetadata); + expect(metadataConsensus?.toString()).to.equal(expectedMetadata); const metadataMirror = await ( await mirrorNodeClient.getTokenData(tokenId) @@ -5110,9 +5117,9 @@ describe("TokenCreateTransaction", function () { expect(Buffer.from(metadataMirror, "base64").toString("utf8")).to.equal( expectedMetadata, ); - } + }; - it("(#1) Creates a token with metadata", async function () { + it("(#1) Creates a token with metadata", async () => { const metadataValue = "1234"; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -5124,7 +5131,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenCreationWithMetadata(response.tokenId, metadataValue); }); - it("(#2) Creates a token with empty metadata", async function () { + it("(#2) Creates a token with empty metadata", async () => { const metadata = ""; const response = await JSONRPCRequest(this, "createToken", { name: "testname", @@ -5137,8 +5144,8 @@ describe("TokenCreateTransaction", function () { }); }); - describe("Metadata Key", function () { - it("(#1) Creates a token with a valid ED25519 public key as its metadata key", async function () { + describe("Metadata Key", () => { + it("(#1) Creates a token with a valid ED25519 public key as its metadata key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -5156,7 +5163,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "metadataKey"); }); - it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its metadata key", async function () { + it("(#2) Creates a token with a valid ECDSAsecp256k1 public key as its metadata key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -5173,7 +5180,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "metadataKey"); }); - it("(#3) Creates a token with a valid ED25519 private key as its metadata key", async function () { + it("(#3) Creates a token with a valid ED25519 private key as its metadata key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -5197,7 +5204,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "metadataKey"); }); - it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its metadata key", async function () { + it("(#4) Creates a token with a valid ECDSAsecp256k1 private key as its metadata key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -5221,7 +5228,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKey(response.tokenId, publicKey, "metadataKey"); }); - it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { + it("(#5) Creates a token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -5240,7 +5247,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, keyList, "metadataKey"); }); - it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its metadata key", async function () { + it("(#6) Creates a token with a valid KeyList of nested Keylists (three levels) as its metadata key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -5259,7 +5266,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, nestedKeyList, "metadataKey"); }); - it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { + it("(#7) Creates a token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "thresholdKey", threshold: 2, @@ -5288,7 +5295,7 @@ describe("TokenCreateTransaction", function () { await verifyTokenKeyList(response.tokenId, thresholdKey, "metadataKey"); }); - it("(#8) 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 () => { try { await JSONRPCRequest(this, "createToken", { name: "testname", @@ -5296,7 +5303,7 @@ describe("TokenCreateTransaction", function () { treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, metadataKey: crypto.randomBytes(88).toString("hex"), }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } diff --git a/test/token-service/test_tokenDeleteTransaction.js b/src/tests/token-service/test-token-delete-transaction.ts similarity index 82% rename from test/token-service/test_tokenDeleteTransaction.js rename to src/tests/token-service/test-token-delete-transaction.ts index e08ac96..4675d60 100644 --- a/test/token-service/test_tokenDeleteTransaction.js +++ b/src/tests/token-service/test-token-delete-transaction.ts @@ -1,13 +1,11 @@ import { assert } from "chai"; -import { JSONRPCRequest } from "../../client.js"; -import { setOperator } from "../../setup_Tests.js"; - -import { - verifyTokenIsDeleted, - getNewFungibleTokenId, -} from "../../utils/helpers/token.js"; -import { retryOnError } from "../../utils/helpers/retry-on-error.js"; +import { JSONRPCRequest } from "@services/Client"; + +import { setOperator } from "@helpers/setup-tests"; +import { verifyTokenIsDeleted, getNewFungibleTokenId } from "@helpers/token"; +import { retryOnError } from "@helpers/retry-on-error"; + /** * Tests for TokenDeleteTransaction */ @@ -16,18 +14,19 @@ describe("TokenDeleteTransaction", function () { this.timeout(30000); // Each test should first establish the network to use, and then teardown the network when complete. - beforeEach(async function () { + beforeEach(async () => { await setOperator( - process.env.OPERATOR_ACCOUNT_ID, - process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + this, + process.env.OPERATOR_ACCOUNT_ID as string, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY as string, ); }); - afterEach(async function () { + afterEach(async () => { await JSONRPCRequest(this, "reset"); }); - describe("Token ID", function () { - it("(#1) Deletes an immutable token", async function () { + describe("Token ID", () => { + it("(#1) Deletes an immutable token", async () => { const response = await JSONRPCRequest(this, "createToken", { name: "testname", symbol: "testsymbol", @@ -43,7 +42,7 @@ describe("TokenDeleteTransaction", function () { signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -52,7 +51,7 @@ describe("TokenDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Deletes a mutable token", async function () { + it("(#2) Deletes a mutable token", async () => { const tokenId = await getNewFungibleTokenId(this); await JSONRPCRequest(this, "deleteToken", { @@ -67,7 +66,7 @@ describe("TokenDeleteTransaction", function () { }); }); - it("(#3) Deletes a token that doesn't exist", async function () { + it("(#3) Deletes a token that doesn't exist", async () => { try { await JSONRPCRequest(this, "deleteToken", { tokenId: "123.456.789", @@ -75,7 +74,7 @@ describe("TokenDeleteTransaction", function () { signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_ID"); return; } @@ -84,7 +83,7 @@ describe("TokenDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Deletes a token with no token ID", async function () { + it("(#4) Deletes a token with no token ID", async () => { try { await JSONRPCRequest(this, "deleteToken", { tokenId: "", @@ -92,7 +91,7 @@ describe("TokenDeleteTransaction", function () { signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.message, "Internal error"); return; } @@ -101,7 +100,7 @@ describe("TokenDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Deletes a token that was already deleted", async function () { + it("(#5) Deletes a token that was already deleted", async () => { try { const tokenId = await getNewFungibleTokenId(this); @@ -119,7 +118,7 @@ describe("TokenDeleteTransaction", function () { signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_WAS_DELETED"); return; } @@ -128,7 +127,7 @@ describe("TokenDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Deletes a token without signing with the token's admin key", async function () { + it("(#6) Deletes a token without signing with the token's admin key", async () => { try { // Passing other admin key in order to throw an error const privateKey = await JSONRPCRequest(this, "generateKey", { @@ -140,7 +139,7 @@ describe("TokenDeleteTransaction", function () { await JSONRPCRequest(this, "deleteToken", { tokenId: tokenId, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -149,7 +148,7 @@ describe("TokenDeleteTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Deletes a token but signs with an incorrect private key", async function () { + it("(#7) Deletes a token but signs with an incorrect private key", async () => { try { const privateKey = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", @@ -174,7 +173,7 @@ describe("TokenDeleteTransaction", function () { signers: [process.env.OPERATOR_ACCOUNT_PRIVATE_KEY], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } diff --git a/test/token-service/test_tokenUpdateTransaction.js b/src/tests/token-service/test-token-update-transaction.ts similarity index 89% rename from test/token-service/test_tokenUpdateTransaction.js rename to src/tests/token-service/test-token-update-transaction.ts index 3f25579..781b7e1 100644 --- a/test/token-service/test_tokenUpdateTransaction.js +++ b/src/tests/token-service/test-token-update-transaction.ts @@ -1,24 +1,24 @@ import crypto from "crypto"; import { assert, expect } from "chai"; -import { JSONRPCRequest } from "../../client.js"; -import mirrorNodeClient from "../../mirrorNodeClient.js"; -import consensusInfoClient from "../../consensusInfoClient.js"; -import { setOperator } from "../../setup_Tests.js"; +import { JSONRPCRequest } from "@services/Client"; +import mirrorNodeClient from "@services/MirrorNodeClient"; +import consensusInfoClient from "@services/ConsensusInfoClient"; -import { retryOnError } from "../../utils/helpers/retry-on-error.js"; +import { setOperator } from "@helpers/setup-tests"; +import { retryOnError } from "@helpers/retry-on-error"; import { verifyTokenKey, verifyTokenKeyList, verifyTokenUpdateWithNullKey, verifyTokenExpirationTimeUpdate, -} from "../../utils/helpers/verify-token-tx.js"; +} from "@helpers/verify-token-tx"; import { fourKeysKeyListParams, twoLevelsNestedKeyListParams, twoThresholdKeyParams, -} from "../../utils/helpers/constants/key-list.js"; +} from "@constants/key-list"; /** * Tests for TokenUpdateTransaction @@ -34,12 +34,13 @@ describe("TokenUpdateTransaction", function () { const initialSupply = "1000000"; // Two tokens should be created. One immutable token (no admin key) and another mutable. - let immutableTokenId, mutableTokenId, mutableTokenKey; + let immutableTokenId: string, mutableTokenId: string, mutableTokenKey: string; - beforeEach(async function () { + beforeEach(async () => { await setOperator( - process.env.OPERATOR_ACCOUNT_ID, - process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + this, + process.env.OPERATOR_ACCOUNT_ID as string, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY as string, ); // Generate an immutable token. @@ -56,10 +57,11 @@ describe("TokenUpdateTransaction", function () { await JSONRPCRequest(this, "reset"); }); - beforeEach(async function () { + beforeEach(async () => { await setOperator( - process.env.OPERATOR_ACCOUNT_ID, - process.env.OPERATOR_ACCOUNT_PRIVATE_KEY, + this, + process.env.OPERATOR_ACCOUNT_ID as string, + process.env.OPERATOR_ACCOUNT_PRIVATE_KEY as string, ); let response = await JSONRPCRequest(this, "generateKey", { @@ -90,20 +92,20 @@ describe("TokenUpdateTransaction", function () { mutableTokenId = response.tokenId; }); - afterEach(async function () { + afterEach(async () => { await JSONRPCRequest(this, "reset"); }); - describe("Token ID", function () { - async function verifyTokenUpdate(tokenId) { + describe("Token ID", () => { + const verifyTokenUpdate = async (tokenId: string) => { 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 () { + it("(#1) Updates an immutable token with no updates", async () => { await JSONRPCRequest(this, "updateToken", { tokenId: immutableTokenId, }); @@ -111,7 +113,7 @@ describe("TokenUpdateTransaction", function () { await retryOnError(async () => verifyTokenUpdate(immutableTokenId)); }); - it("(#2) Updates a mutable token with no updates", async function () { + it("(#2) Updates a mutable token with no updates", async () => { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, }); @@ -119,10 +121,10 @@ describe("TokenUpdateTransaction", function () { await retryOnError(async () => verifyTokenUpdate(mutableTokenId)); }); - it("(#3) Updates a token with no token ID", async function () { + it("(#3) Updates a token with no token ID", async () => { try { await JSONRPCRequest(this, "updateToken", {}); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_TOKEN_ID"); return; } @@ -131,27 +133,25 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Symbol", function () { - async function verifyTokenSymbolUpdate(tokenId, symbol) { + describe("Symbol", () => { + const verifyTokenSymbolUpdate = async (tokenId: string, symbol: string) => { expect(symbol).to.equal( - await ( - await consensusInfoClient.getTokenInfo(tokenId) - ).symbol, + (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 () { + it("(#1) Updates an immutable token with a symbol", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: immutableTokenId, symbol: "t", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -159,7 +159,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a symbol that is the minimum length", async function () { + it("(#2) Updates a mutable token with a symbol that is the minimum length", async () => { const symbol = "t"; await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -174,7 +174,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#3) Updates a mutable token with a symbol that is empty", async function () { + it("(#3) Updates a mutable token with a symbol that is empty", async () => { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, symbol: "", @@ -189,7 +189,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#4) Updates a mutable token with a symbol that is the maximum length", async function () { + it("(#4) Updates a mutable token with a symbol that is the maximum length", async () => { const symbol = "This is a really long symbol but it is still valid because it is 100 characters exactly on the money"; await JSONRPCRequest(this, "updateToken", { @@ -205,7 +205,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#5) Updates a mutable token with a symbol that exceeds the maximum length", async function () { + it("(#5) Updates a mutable token with a symbol that exceeds the maximum length", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -215,7 +215,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_SYMBOL_TOO_LONG"); return; } @@ -223,13 +223,13 @@ describe("TokenUpdateTransaction", function () { 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 symbol without signing with the token's admin key", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, symbol: "t", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -238,12 +238,10 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Name", function () { - async function verifyTokenNameUpdate(tokenId, name) { + describe("Name", () => { + const verifyTokenNameUpdate = async (tokenId: string, name: string) => { expect(name).to.equal( - await ( - await consensusInfoClient.getTokenInfo(tokenId) - ).name, + (await consensusInfoClient.getTokenInfo(tokenId)).name, ); expect(name).to.equal( @@ -251,15 +249,15 @@ describe("TokenUpdateTransaction", function () { await mirrorNodeClient.getTokenData(tokenId) ).name, ); - } + }; - it("(#1) Updates an immutable token with a name", async function () { + it("(#1) Updates an immutable token with a name", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: immutableTokenId, name: "t", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -267,7 +265,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a name that is the minimum length", async function () { + it("(#2) Updates a mutable token with a name that is the minimum length", async () => { const name = "t"; await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -282,7 +280,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#3) Updates a mutable token with a name that is empty", async function () { + it("(#3) Updates a mutable token with a name that is empty", async () => { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, name: "", @@ -297,7 +295,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#4) Updates a mutable token with a name that is the maximum length", async function () { + it("(#4) Updates a mutable token with a name that is the maximum length", async () => { const name = "This is a really long name but it is still valid because it is 100 characters exactly on the money!!"; await JSONRPCRequest(this, "updateToken", { @@ -313,7 +311,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#5) Updates a mutable token with a name that exceeds the maximum length", async function () { + it("(#5) Updates a mutable token with a name that exceeds the maximum length", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -322,7 +320,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_NAME_TOO_LONG"); return; } @@ -330,13 +328,13 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Updates a mutable token with a valid name 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, name: "t", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -345,14 +343,14 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Treasury Account ID", function () { - it("(#1) Updates an immutable token with a treasury account", async function () { + describe("Treasury Account ID", () => { + it("(#1) Updates an immutable token with a treasury account", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: immutableTokenId, treasuryAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -360,7 +358,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a treasury account", async function () { + it("(#2) Updates a mutable token with a treasury account", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -384,28 +382,30 @@ describe("TokenUpdateTransaction", function () { }); const tokenInfo = await consensusInfoClient.getTokenInfo(mutableTokenId); - expect(accountId).to.equal(tokenInfo.treasuryAccountId.toString()); + 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); + await consensusInfoClient.getBalance( + process.env.OPERATOR_ACCOUNT_ID as string, + ); const newTreasuryAccountBalance = await consensusInfoClient.getBalance(accountId); - assert(initialTreasuryAccountBalance.tokens._map.has(mutableTokenId)); - assert(newTreasuryAccountBalance.tokens._map.has(mutableTokenId)); + assert(initialTreasuryAccountBalance.tokens?._map.has(mutableTokenId)); + assert(newTreasuryAccountBalance.tokens?._map.has(mutableTokenId)); expect( - initialTreasuryAccountBalance.tokens._map + initialTreasuryAccountBalance.tokens?._map .get(mutableTokenId) - .toString(), + ?.toString(), ).to.equal("0"); expect( - newTreasuryAccountBalance.tokens._map.get(mutableTokenId).toString(), + 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 () { + it("(#3) Updates a mutable token with a treasury account without signing with the account's private key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -426,7 +426,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -434,7 +434,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Updates a mutable token with a treasury account that doesn't exist", async function () { + it("(#4) Updates a mutable token with a treasury account that doesn't exist", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -443,7 +443,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_ACCOUNT_ID"); return; } @@ -451,7 +451,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Updates a mutable token with a treasury account that is deleted", async function () { + it("(#5) Updates a mutable token with a treasury account that is deleted", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -480,7 +480,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey, key], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "ACCOUNT_DELETED"); return; } @@ -488,7 +488,7 @@ describe("TokenUpdateTransaction", function () { 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 () { + it("(#6) Updates a mutable token with a treasury account without signing with the token's admin key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -509,7 +509,7 @@ describe("TokenUpdateTransaction", function () { signers: [key], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -518,8 +518,8 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Admin Key", function () { - it("(#1) Updates an immutable token with a valid key as its admin key", async function () { + describe("Admin Key", () => { + it("(#1) Updates an immutable token with a valid key as its admin key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -531,7 +531,7 @@ describe("TokenUpdateTransaction", function () { tokenId: immutableTokenId, adminKey: key, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -539,7 +539,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a valid ED25519 public key as its admin key", async function () { + it("(#2) Updates a mutable token with a valid ED25519 public key as its admin key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -566,7 +566,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#3) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -593,7 +593,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#4) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -620,7 +620,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#5) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -647,7 +647,7 @@ describe("TokenUpdateTransaction", 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 () { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async () => { const keyList = await JSONRPCRequest( this, "generateKey", @@ -673,7 +673,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#7) Updates a mutable 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 () => { const nestedKeyList = await JSONRPCRequest( this, "generateKey", @@ -701,7 +701,7 @@ describe("TokenUpdateTransaction", 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 () { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its admin key", async () => { const thresholdKey = await JSONRPCRequest( this, "generateKey", @@ -725,7 +725,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#9) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -740,7 +740,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -748,7 +748,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#10) Updates a mutable 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -757,7 +757,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -766,8 +766,8 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("KYC Key", function () { - it("(#1) Updates an immutable token with a valid key as its KYC key", async function () { + describe("KYC Key", () => { + it("(#1) Updates an immutable token with a valid key as its KYC key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -779,7 +779,7 @@ describe("TokenUpdateTransaction", function () { tokenId: immutableTokenId, kycKey: key, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -787,7 +787,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a valid ED25519 public key as its KYC key", async function () { + it("(#2) Updates a mutable token with a valid ED25519 public key as its KYC key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -808,7 +808,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#3) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -829,7 +829,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#4) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -856,7 +856,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#5) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -883,7 +883,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async () => { const keyList = await JSONRPCRequest( this, "generateKey", @@ -909,7 +909,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its KYC key", async function () { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its KYC key", async () => { const nestedKeyList = await JSONRPCRequest( this, "generateKey", @@ -937,7 +937,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async function () { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its KYC key", async () => { const thresholdKey = await JSONRPCRequest( this, "generateKey", @@ -961,7 +961,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "keyList", keys: [], @@ -982,7 +982,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#10) Updates a mutable token that doesn't have a KYC key with a valid key as its KYC key", async function () { + it("(#10) Updates a mutable token that doesn't have a KYC key with a valid key as its KYC key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -1010,7 +1010,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_HAS_NO_KYC_KEY"); return; } @@ -1018,7 +1018,7 @@ 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 () { + it("(#11) Updates a mutable token with an invalid key as its KYC key", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -1027,7 +1027,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -1036,8 +1036,8 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Freeze Key", function () { - it("(#1) Updates an immutable token with a valid key as its freeze key", async function () { + describe("Freeze Key", () => { + it("(#1) Updates an immutable token with a valid key as its freeze key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -1049,7 +1049,7 @@ describe("TokenUpdateTransaction", function () { tokenId: immutableTokenId, freezeKey: key, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -1057,7 +1057,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a valid ED25519 public key as its freeze key", async function () { + it("(#2) Updates a mutable token with a valid ED25519 public key as its freeze key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1084,7 +1084,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#3) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -1111,7 +1111,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#4) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1138,7 +1138,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#5) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -1165,7 +1165,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async () => { const keyList = await JSONRPCRequest( this, "generateKey", @@ -1191,7 +1191,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its freeze key", async function () { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its freeze key", async () => { const nestedKeyList = await JSONRPCRequest( this, "generateKey", @@ -1219,7 +1219,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async function () { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its freeze key", async () => { const thresholdKey = await JSONRPCRequest( this, "generateKey", @@ -1243,7 +1243,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "keyList", keys: [], @@ -1264,7 +1264,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#10) Updates a mutable token that doesn't have a freeze key with a valid key as its freeze key", async function () { + it("(#10) Updates a mutable token that doesn't have a freeze key with a valid key as its freeze key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -1292,7 +1292,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_HAS_NO_FREEZE_KEY"); return; } @@ -1300,7 +1300,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -1309,7 +1309,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -1318,8 +1318,8 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Wipe Key", function () { - it("(#1) Updates an immutable token with a valid key as its wipe key", async function () { + describe("Wipe Key", () => { + it("(#1) Updates an immutable token with a valid key as its wipe key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -1331,7 +1331,7 @@ describe("TokenUpdateTransaction", function () { tokenId: immutableTokenId, wipeKey: key, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -1339,7 +1339,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a valid ED25519 public key as its wipe key", async function () { + it("(#2) Updates a mutable token with a valid ED25519 public key as its wipe key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1366,7 +1366,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#3) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -1393,7 +1393,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#4) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1420,7 +1420,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#5) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -1447,7 +1447,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async () => { const keyList = await JSONRPCRequest( this, "generateKey", @@ -1473,7 +1473,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its wipe key", async function () { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its wipe key", async () => { const nestedKeyList = await JSONRPCRequest( this, "generateKey", @@ -1501,7 +1501,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async function () { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its wipe key", async () => { const thresholdKey = await JSONRPCRequest( this, "generateKey", @@ -1525,7 +1525,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "keyList", keys: [], @@ -1546,7 +1546,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#10) Updates a mutable token that doesn't have a wipe key with a valid key as its wipe key", async function () { + it("(#10) Updates a mutable token that doesn't have a wipe key with a valid key as its wipe key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -1574,7 +1574,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_HAS_NO_WIPE_KEY"); return; } @@ -1582,7 +1582,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -1591,7 +1591,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -1600,8 +1600,8 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Supply Key", function () { - it("(#1) Updates an immutable token with a valid key as its supply key", async function () { + describe("Supply Key", () => { + it("(#1) Updates an immutable token with a valid key as its supply key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -1613,7 +1613,7 @@ describe("TokenUpdateTransaction", function () { tokenId: immutableTokenId, supplyKey: key, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -1621,7 +1621,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a valid ED25519 public key as its supply key", async function () { + it("(#2) Updates a mutable token with a valid ED25519 public key as its supply key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1648,7 +1648,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its supply key", async function () { + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its supply key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -1675,7 +1675,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#4) Updates a mutable token with a valid ED25519 private key as its supply key", async function () { + it("(#4) Updates a mutable token with a valid ED25519 private key as its supply key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1702,7 +1702,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its supply key", async function () { + it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key as its supply key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -1729,7 +1729,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async () => { const keyList = await JSONRPCRequest( this, "generateKey", @@ -1755,7 +1755,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its supply key", async function () { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its supply key", async () => { const nestedKeyList = await JSONRPCRequest( this, "generateKey", @@ -1783,7 +1783,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async function () { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its supply key", async () => { const thresholdKey = await JSONRPCRequest( this, "generateKey", @@ -1807,7 +1807,7 @@ describe("TokenUpdateTransaction", function () { ); }); - it("(#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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "keyList", keys: [], @@ -1828,7 +1828,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#10) Updates a mutable token that doesn't have a supply key with a valid key as its supply key", async function () { + it("(#10) Updates a mutable token that doesn't have a supply key with a valid key as its supply key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -1856,7 +1856,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_HAS_NO_SUPPLY_KEY"); return; } @@ -1864,7 +1864,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -1873,7 +1873,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -1882,14 +1882,14 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Auto Renew Account", function () { - it("(#1) Updates an immutable token with an auto renew account", async function () { + describe("Auto Renew Account", () => { + it("(#1) Updates an immutable token with an auto renew account", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: immutableTokenId, autoRenewAccountId: process.env.OPERATOR_ACCOUNT_ID, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -1897,7 +1897,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with an auto renew account", async function () { + it("(#2) Updates a mutable token with an auto renew account", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1919,10 +1919,11 @@ describe("TokenUpdateTransaction", function () { }); const tokenInfo = await consensusInfoClient.getTokenInfo(mutableTokenId); - expect(accountId).to.equal(tokenInfo.autoRenewAccountId.toString()); + + 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 () { + it("(#3) Updates a mutable token with an auto renew account without signing with the account's private key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -1943,7 +1944,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -1951,16 +1952,16 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Updates a mutable token with an auto renew account that doesn't exist", async function () { + it("(#4) Updates a mutable token with an auto renew account that doesn't exist", async () => { try { - response = await JSONRPCRequest(this, "updateToken", { + await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, autoRenewAccountId: "123.456.789", commonTransactionParams: { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); return; } @@ -1968,16 +1969,16 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Updates a mutable token with an empty auto renew account", async function () { + it("(#5) Updates a mutable token with an empty auto renew account", async () => { try { - response = await JSONRPCRequest(this, "updateToken", { + await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, autoRenewAccountId: "", commonTransactionParams: { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -1985,7 +1986,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#6) Updates a mutable token with an auto renew account that is deleted", async function () { + it("(#6) Updates a mutable token with an auto renew account that is deleted", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -2014,7 +2015,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey, key], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_AUTORENEW_ACCOUNT"); return; } @@ -2022,7 +2023,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) Updates a mutable token with an auto renew account without signing with the token's admin key", async function () { + it("(#7) Updates a mutable token with an auto renew account without signing with the token's admin key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -2043,7 +2044,7 @@ describe("TokenUpdateTransaction", function () { signers: [key], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_SIGNATURE"); return; } @@ -2052,12 +2053,13 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Auto Renew Period", function () { - async function verifyTokenAutoRenewPeriodUpdate(tokenId, autoRenewPeriod) { + describe("Auto Renew Period", () => { + const verifyTokenAutoRenewPeriodUpdate = async ( + tokenId: string, + autoRenewPeriod: string, + ) => { expect(autoRenewPeriod).to.equal( - await ( - await consensusInfoClient.getTokenInfo(tokenId) - ).autoRenewPeriod, + (await consensusInfoClient.getTokenInfo(tokenId)).autoRenewPeriod, ); expect(autoRenewPeriod).to.equal( @@ -2065,15 +2067,15 @@ describe("TokenUpdateTransaction", function () { 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: immutableTokenId, autoRenewPeriod: "5184000", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -2081,7 +2083,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with an auto renew period set to 0 seconds", async function () { + it("(#2) Updates a mutable token with an auto renew period set to 0 seconds", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2090,7 +2092,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2098,7 +2100,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Updates a mutable token with an auto renew period set to -1 seconds", async function () { + it("(#3) Updates a mutable token with an auto renew period set to -1 seconds", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2107,7 +2109,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2115,7 +2117,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - 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 () { + it("(#4) Updates a mutable token with an auto renew period set to 9,223,372,036,854,775,807 (int64 max) seconds", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2124,7 +2126,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2132,7 +2134,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - 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 () { + 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2141,7 +2143,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2149,7 +2151,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - 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 () { + 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2158,7 +2160,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2166,7 +2168,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - 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 () { + 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2175,7 +2177,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2183,7 +2185,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#8) 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 () => { const autoRenewPeriod = "5184000"; await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2198,7 +2200,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#9) 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 () => { const autoRenewPeriod = "2592000"; await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2213,7 +2215,7 @@ describe("TokenUpdateTransaction", 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 () { + it("(#10) Updates a mutable token with an auto renew period set to 30 days minus one second (2,591,999 seconds)", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2222,7 +2224,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2230,7 +2232,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) 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 () => { const autoRenewPeriod = "8000001"; await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2245,7 +2247,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#12) 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2254,7 +2256,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_RENEWAL_PERIOD"); return; } @@ -2263,8 +2265,8 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Expiration Time", function () { - it.skip("(#1) Updates an immutable token with a valid expiration time", async function () { + describe("Expiration Time", () => { + it.skip("(#1) Updates an immutable token with a valid expiration time", async () => { const expirationTime = ( Math.floor(Date.now() / 1000) + 5184000 ).toString(); @@ -2274,7 +2276,7 @@ describe("TokenUpdateTransaction", function () { tokenId: immutableTokenId, expirationTime, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -2282,7 +2284,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token to an expiration time of 0", async function () { + it("(#2) Updates a mutable token to an expiration time of 0", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2291,7 +2293,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -2299,7 +2301,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#3) Updates a mutable token to an expiration time of -1", async function () { + it("(#3) Updates a mutable token to an expiration time of -1", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2308,7 +2310,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -2316,7 +2318,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#4) Updates a mutable token to an expiration time of 9,223,372,036,854,775,807 (int64 max) seconds", async function () { + it("(#4) Updates a mutable token to an expiration time of 9,223,372,036,854,775,807 (int64 max) seconds", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2325,7 +2327,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -2333,7 +2335,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#5) Updates a mutable token to an expiration time of 9,223,372,036,854,775,806 (int64 max - 1) seconds", 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2342,7 +2344,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -2350,7 +2352,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#6) Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async function () { + it.skip("(#6) Updates a mutable token to an expiration time of -9,223,372,036,854,775,808 (int64 min) seconds", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2359,7 +2361,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -2367,7 +2369,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#7) 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2376,7 +2378,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -2384,12 +2386,12 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it.skip("(#8) Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time", async function () { + it.skip("(#8) Updates a mutable token to an expiration time of 60 days (5,184,000 seconds) from the current time", async () => { const expirationTime = ( Math.floor(Date.now() / 1000) + 5184000 ).toString(); - await JSONRPCRequest(this, "updateToken", { + const response = await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, expirationTime, commonTransactionParams: { @@ -2397,15 +2399,17 @@ describe("TokenUpdateTransaction", function () { }, }); - verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + await retryOnError(async () => { + verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + }); }); - it.skip("(#9) Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time", async function () { + it.skip("(#9) Updates a mutable token to an expiration time of 30 days (2,592,000 seconds) from the current time", async () => { const expirationTime = ( Math.floor(Date.now() / 1000) + 2592000 ).toString(); - await JSONRPCRequest(this, "updateToken", { + const response = await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, expirationTime, commonTransactionParams: { @@ -2413,10 +2417,12 @@ describe("TokenUpdateTransaction", function () { }, }); - verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + await retryOnError(async () => { + verifyTokenExpirationTimeUpdate(response.tokenId, expirationTime); + }); }); - 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 () { + it("(#10) Updates a mutable to an expiration time of 30 days minus one second (2,591,999 seconds) from the current time", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2425,7 +2431,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -2433,7 +2439,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) 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 () => { const expirationTime = ( Math.floor(Date.now() / 1000) + 8000001 ).toString(); @@ -2451,7 +2457,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#12) 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2460,7 +2466,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "INVALID_EXPIRATION_TIME"); return; } @@ -2469,12 +2475,10 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Memo", function () { - async function verifyTokenMemoUpdate(tokenId, memo) { + describe("Memo", () => { + const verifyTokenMemoUpdate = async (tokenId: string, memo: string) => { expect(memo).to.equal( - await ( - await consensusInfoClient.getTokenInfo(tokenId) - ).memo, + (await consensusInfoClient.getTokenInfo(tokenId)).tokenMemo, ); expect(memo).to.equal( @@ -2482,15 +2486,15 @@ describe("TokenUpdateTransaction", function () { 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: immutableTokenId, memo: "testmemo", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -2498,7 +2502,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a memo that is a valid length", async function () { + it("(#2) Updates a mutable token with a memo that is a valid length", async () => { const memo = "testmemo"; await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2513,7 +2517,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#3) Updates a mutable token with a memo that is the minimum length", async function () { + it("(#3) Updates a mutable token with a memo that is the minimum length", async () => { const memo = ""; await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2528,7 +2532,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#4) Updates a mutable token with a memo that is the minimum length", async function () { + it("(#4) Updates a mutable token with a memo that is the minimum length", async () => { const memo = "This is a really long memo but it is still valid because it is 100 characters exactly on the money!!"; await JSONRPCRequest(this, "updateToken", { @@ -2544,7 +2548,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#5) Updates a mutable token with a memo that exceeds the maximum length", async function () { + it("(#5) Updates a mutable token with a memo that exceeds the maximum length", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2553,7 +2557,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "MEMO_TOO_LONG"); return; } @@ -2562,8 +2566,8 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Fee Schedule Key", function () { - it("(#1) Updates an immutable token with a valid key as its fee schedule key", async function () { + describe("Fee Schedule Key", () => { + it("(#1) Updates an immutable token with a valid key as its fee schedule key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -2575,7 +2579,7 @@ describe("TokenUpdateTransaction", function () { tokenId: immutableTokenId, feeScheduleKey: key, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -2583,7 +2587,7 @@ describe("TokenUpdateTransaction", function () { 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 () { + it("(#2) Updates a mutable token with a valid ED25519 public key as its fee schedule key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -2610,7 +2614,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its fee schedule key", async function () { + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its fee schedule key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -2637,7 +2641,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#4) Updates a mutable token with a valid ED25519 private key as its fee schedule key", async function () { + it("(#4) Updates a mutable token with a valid ED25519 private key as its fee schedule key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -2664,7 +2668,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#5) Updates a mutable token with a valid ECDSAsecp256k1 private key 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -2691,7 +2695,7 @@ describe("TokenUpdateTransaction", function () { }); }); - 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 () { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async () => { const keyList = await JSONRPCRequest( this, "generateKey", @@ -2711,7 +2715,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its fee schedule key", async function () { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its fee schedule key", async () => { const nestedKeyList = await JSONRPCRequest( this, "generateKey", @@ -2731,7 +2735,7 @@ describe("TokenUpdateTransaction", function () { }); }); - 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 () { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its fee schedule key", async () => { const thresholdKey = await JSONRPCRequest( this, "generateKey", @@ -2751,7 +2755,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "keyList", keys: [], @@ -2772,7 +2776,7 @@ describe("TokenUpdateTransaction", function () { }); }); - 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 () { + it("(#10) Updates a mutable token that doesn't have a fee schedule key with a valid key as its fee schedule key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -2800,7 +2804,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_HAS_NO_FEE_SCHEDULE_KEY"); return; } @@ -2808,7 +2812,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -2817,7 +2821,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -2826,8 +2830,8 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Pause Key", function () { - it("(#1) Updates an immutable token with a valid key as its pause key", async function () { + describe("Pause Key", () => { + it("(#1) Updates an immutable token with a valid key as its pause key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -2839,7 +2843,7 @@ describe("TokenUpdateTransaction", function () { tokenId: immutableTokenId, feeScheduleKey: key, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -2847,7 +2851,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a valid ED25519 public key as its pause key", async function () { + it("(#2) Updates a mutable token with a valid ED25519 public key as its pause key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -2867,7 +2871,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its pause key", async function () { + it("(#3) Updates a mutable token with a valid ECDSAsecp256k1 public key as its pause key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -2887,7 +2891,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#4) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -2914,7 +2918,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#5) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -2941,7 +2945,7 @@ describe("TokenUpdateTransaction", 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 () { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -2963,7 +2967,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its pause key", async function () { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its pause key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -2985,7 +2989,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async function () { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its pause key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -3007,7 +3011,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "keyList", keys: [], @@ -3028,7 +3032,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#10) Updates a mutable token that doesn't have a pause key with a valid key as its pause key", async function () { + it("(#10) Updates a mutable token that doesn't have a pause key with a valid key as its pause key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -3056,7 +3060,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_HAS_NO_PAUSE_KEY"); return; } @@ -3064,7 +3068,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -3073,7 +3077,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } @@ -3082,23 +3086,26 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Metadata", function () { - async function verifyTokenMetadataUpdate(tokenId, metadata) { + describe("Metadata", () => { + const verifyTokenMetadataUpdate = async ( + tokenId: string, + metadata: string, + ) => { expect(metadata).to.equal( - await consensusInfoClient.getTokenInfo(tokenId).metadata, + (await consensusInfoClient.getTokenInfo(tokenId)).metadata, ); expect(metadata).to.equal( - await mirrorNodeClient.getTokenData(tokenId).tokens[0].metadata, + (await mirrorNodeClient.getTokenData(tokenId))?.metadata, ); - } + }; - it("(#1) Updates an immutable token with metadata", async function () { + it("(#1) Updates an immutable token with metadata", async () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: immutableTokenId, metadata: "1234", }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -3106,7 +3113,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with metadata", async function () { + it("(#2) Updates a mutable token with metadata", async () => { const metadata = "1234"; await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -3121,7 +3128,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#3) Updates a mutable token with empty metadata", async function () { + it("(#3) Updates a mutable token with empty metadata", async () => { const metadata = ""; await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -3137,8 +3144,8 @@ describe("TokenUpdateTransaction", function () { }); }); - describe("Metadata Key", function () { - it("(#1) Updates an immutable token with a valid key as its metadata key", async function () { + describe("Metadata Key", () => { + it("(#1) Updates an immutable token with a valid key as its metadata key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -3150,7 +3157,7 @@ describe("TokenUpdateTransaction", function () { tokenId: immutableTokenId, metadataKey: key, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_IS_IMMUTABLE"); return; } @@ -3158,7 +3165,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#2) Updates a mutable token with a valid ED25519 public key as its metadata key", async function () { + it("(#2) Updates a mutable token with a valid ED25519 public key as its metadata key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PublicKey", }); @@ -3178,7 +3185,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#3) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -3198,7 +3205,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#4) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ed25519PrivateKey", }); @@ -3225,7 +3232,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#5) Updates a mutable 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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PrivateKey", }); @@ -3252,7 +3259,7 @@ describe("TokenUpdateTransaction", 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 () { + it("(#6) Updates a mutable token with a valid KeyList of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -3274,7 +3281,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its metadata key", async function () { + it("(#7) Updates a mutable token with a valid KeyList of nested Keylists (three levels) as its metadata key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -3296,7 +3303,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async function () { + it("(#8) Updates a mutable token with a valid ThresholdKey of ED25519 and ECDSAsecp256k1 private and public keys as its metadata key", async () => { let response = await JSONRPCRequest( this, "generateKey", @@ -3318,7 +3325,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#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 () => { let response = await JSONRPCRequest(this, "generateKey", { type: "keyList", keys: [], @@ -3339,7 +3346,7 @@ describe("TokenUpdateTransaction", function () { }); }); - it("(#10) Updates a mutable token that doesn't have a metadata key with a valid key as its metadata key", async function () { + it("(#10) Updates a mutable token that doesn't have a metadata key with a valid key as its metadata key", async () => { let response = await JSONRPCRequest(this, "generateKey", { type: "ecdsaSecp256k1PublicKey", }); @@ -3367,7 +3374,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.data.status, "TOKEN_HAS_NO_METADATA_KEY"); return; } @@ -3375,7 +3382,7 @@ describe("TokenUpdateTransaction", function () { assert.fail("Should throw an error"); }); - it("(#11) 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 () => { try { await JSONRPCRequest(this, "updateToken", { tokenId: mutableTokenId, @@ -3384,7 +3391,7 @@ describe("TokenUpdateTransaction", function () { signers: [mutableTokenKey], }, }); - } catch (err) { + } catch (err: any) { assert.equal(err.code, -32603, "Internal error"); return; } diff --git a/utils/helpers/asn1-decoder.js b/src/utils/helpers/asn1-decoder.ts similarity index 54% rename from utils/helpers/asn1-decoder.js rename to src/utils/helpers/asn1-decoder.ts index 24210d8..4bc533e 100644 --- a/utils/helpers/asn1-decoder.js +++ b/src/utils/helpers/asn1-decoder.ts @@ -2,45 +2,28 @@ * Class representing an ASN.1 decoder. */ class ASN1Decoder { + private data: Uint8Array; + private pos: number = 0; + private oids: string[] = []; + private oidMap: Record = { + "1.3.132.0.10": "ecdsa", + "1.3.101.112": "ed25519", + "1.2.840.10045.2.1": "pubkey", + }; + /** * Creates an ASN.1 decoder instance. - * @param {ArrayBuffer | Uint8Array} data - The ASN.1 encoded data to decode. + * @param data - The ASN.1 encoded data to decode. */ - constructor(data) { - /** - * The data to be decoded. - * @type {Uint8Array} - */ + constructor(data: ArrayBuffer | Uint8Array) { this.data = new Uint8Array(data); - - /** - * The current position in the data. - * @type {number} - */ - this.pos = 0; - - /** - * The list of decoded Object Identifiers (OIDs). - * @type {string[]} - */ - this.oids = []; - - /** - * A map of known OID values to their string representations. - * @type {Object.} - */ - this.oidMap = { - "1.3.132.0.10": "ecdsa", - "1.3.101.112": "ed25519", - "1.2.840.10045.2.1": "pubkey", - }; } /** * Reads the length of the current ASN.1 data element. - * @returns {number} The length of the data element. + * @returns The length of the data element. */ - readLength() { + private readLength(): number { let length = this.data[this.pos++]; if (length & 0x80) { let numBytes = length & 0x7f; @@ -54,18 +37,18 @@ class ASN1Decoder { /** * Reads the type of the current ASN.1 data element. - * @returns {number} The type of the data element. + * @returns The type of the data element. */ - readType() { + private readType(): number { return this.data[this.pos++]; } /** * Reads an INTEGER ASN.1 data element. - * @returns {Object} An object containing the decoded integer. + * @returns An object containing the decoded integer. */ - readInteger() { - let length = this.readLength(); + private readInteger(): { integer: number } { + const length = this.readLength(); let value = 0; for (let i = 0; i < length; i++) { value = (value << 8) | this.data[this.pos++]; @@ -75,43 +58,43 @@ class ASN1Decoder { /** * Reads an OCTET STRING ASN.1 data element. - * @returns {Object} An object containing the decoded private key. + * @returns An object containing the decoded private key. */ - readOctetString() { - let length = this.readLength(); - let value = this.data.slice(this.pos, this.pos + length); + private readOctetString(): { pkey: Uint8Array } { + const length = this.readLength(); + const value = this.data.slice(this.pos, this.pos + length); this.pos += length; return { pkey: value }; } /** * Reads a BIT STRING ASN.1 data element. - * @returns {Object} An object containing the number of unused bits + * @returns An object containing the number of unused bits. */ - readBitString() { - let length = this.readLength(); - let unusedBits = this.data[this.pos++]; - let value = this.data.slice(this.pos, this.pos + length - 1); + private readBitString(): { unusedBits: number; pubkey: Uint8Array } { + const length = this.readLength(); + const unusedBits = this.data[this.pos++]; + const value = this.data.slice(this.pos, this.pos + length - 1); this.pos += length - 1; return { unusedBits, pubkey: value }; } /** * Reads an OBJECT IDENTIFIER (OID) ASN.1 data element. - * @returns {Object} An object containing the decoded OID as a string. + * @returns An object containing the decoded OID as a string. */ - readObjectIdentifier() { - let length = this.readLength(); - let endPos = this.pos + length; - let oid = []; + private readObjectIdentifier(): { oid: string } { + const length = this.readLength(); + const endPos = this.pos + length; + const oid: number[] = []; let value = 0; - let firstByte = this.data[this.pos++]; + const firstByte = this.data[this.pos++]; oid.push(Math.floor(firstByte / 40)); oid.push(firstByte % 40); while (this.pos < endPos) { - let byte = this.data[this.pos++]; + const byte = this.data[this.pos++]; value = (value << 7) | (byte & 0x7f); if (!(byte & 0x80)) { oid.push(value); @@ -119,35 +102,35 @@ class ASN1Decoder { } } - let oidStr = oid.join("."); + const oidStr = oid.join("."); this.oids.push(oidStr); return { oid: oidStr }; } /** * Returns the list of decoded OIDs. - * @returns {string[]} The list of decoded OIDs. + * @returns The list of decoded OIDs. */ - getOids() { + getOids(): string[] { return this.oids; } /** * Returns the list of key types associated with the decoded OIDs. - * @returns {string[]} The list of key types. + * @returns The list of key types. */ - getOidKeyTypes() { + getOidKeyTypes(): string[] { return this.oids.map((oid) => this.oidMap[oid] || "unknown"); } /** * Reads a SEQUENCE ASN.1 data element. - * @returns {Array} An array of decoded items. + * @returns An array of decoded items. */ - readSequence() { - let length = this.readLength(); - let endPos = this.pos + length; - let items = []; + private readSequence(): any[] { + const length = this.readLength(); + const endPos = this.pos + length; + const items: any[] = []; while (this.pos < endPos) { items.push(this.read()); } @@ -156,11 +139,11 @@ class ASN1Decoder { /** * Decodes the next ASN.1 data element based on its type. - * @returns {*} The decoded data element. - * @throws {Error} Throws an error if the type is unsupported. + * @returns The decoded data element. + * @throws If the type is unsupported. */ - read() { - let type = this.readType(); + private read(): any { + const type = this.readType(); switch (type) { case 0x02: return this.readInteger(); @@ -181,13 +164,13 @@ class ASN1Decoder { /** * Extracts the raw key (public or private) from the parsed ASN.1 structure. - * @returns {string} The raw key as a hexadecimal string. - * @throws {Error} If no key is found in the provided data. + * @returns The raw key as a hexadecimal string. + * @throws If no key is found in the provided data. */ - getRawKey() { + getRawKey(): string { const sequence = this.read(); - for (let item of sequence) { + for (const item of sequence) { if (item.pubkey) { return Buffer.from(item.pubkey).toString("hex"); } @@ -202,10 +185,10 @@ class ASN1Decoder { /** * Converts a hexadecimal DER-encoded key to its raw format using ASN1Decoder. - * @param {string} hex - The DER-encoded key as a hexadecimal string. - * @returns {string} The raw key in hexadecimal format. + * @param hex - The DER-encoded key as a hexadecimal string. + * @returns The raw key in hexadecimal format. */ -export const getRawKeyFromHex = (hex) => { +export const getRawKeyFromHex = (hex: string): string => { const data1 = Uint8Array.from(Buffer.from(hex, "hex")); const decoder = new ASN1Decoder(data1); diff --git a/utils/helpers/constants/key-list.js b/src/utils/helpers/constants/key-list.ts similarity index 100% rename from utils/helpers/constants/key-list.js rename to src/utils/helpers/constants/key-list.ts diff --git a/utils/helpers/constants/key-type.js b/src/utils/helpers/constants/key-type.ts similarity index 100% rename from utils/helpers/constants/key-type.js rename to src/utils/helpers/constants/key-type.ts diff --git a/src/utils/helpers/custom-fees.ts b/src/utils/helpers/custom-fees.ts new file mode 100644 index 0000000..f2b5359 --- /dev/null +++ b/src/utils/helpers/custom-fees.ts @@ -0,0 +1,283 @@ +import { expect } from "chai"; +import { + CustomFee, + CustomFixedFee, + CustomFractionalFee, + CustomRoyaltyFee, +} from "@hashgraph/sdk"; + +import mirrorNodeClient from "@services/MirrorNodeClient"; +import consensusInfoClient from "@services/ConsensusInfoClient"; + +const consensusNodeFeeEqualsCustomFee = ( + customFee: CustomFee, + feeCollectorAccountId: string, + feeCollectorsExempt: boolean, +) => { + return ( + feeCollectorAccountId === customFee.feeCollectorAccountId?.toString() && + feeCollectorsExempt === customFee.allCollectorsAreExempt + ); +}; + +const consensusNodeFeeEqualsCustomFixedFee = ( + customFixedFee: CustomFixedFee, + feeCollectorAccountId: string, + feeCollectorsExempt: boolean, + amount: string, +) => { + return ( + consensusNodeFeeEqualsCustomFee( + customFixedFee, + feeCollectorAccountId, + feeCollectorsExempt, + ) && amount === customFixedFee.amount?.toString() + ); +}; + +const consensusNodeFeeEqualsCustomFractionalFee = ( + customFractionalFee: CustomFractionalFee, + feeCollectorAccountId: string, + feeCollectorsExempt: boolean, + numerator: string, + denominator: string, + minAmount: string, + maxAmount: string, + assessmentMethod: string, +) => { + return ( + consensusNodeFeeEqualsCustomFee( + customFractionalFee, + feeCollectorAccountId, + feeCollectorsExempt, + ) && + numerator === customFractionalFee.numerator?.toString() && + denominator === customFractionalFee.denominator?.toString() && + minAmount === customFractionalFee.min?.toString() && + maxAmount === customFractionalFee.max?.toString() && + (assessmentMethod === "exclusive") === + customFractionalFee.assessmentMethod?._value + ); +}; + +const consensusNodeFeeEqualsCustomRoyaltyFee = ( + customRoyaltyFee: CustomRoyaltyFee, + feeCollectorAccountId: string, + feeCollectorsExempt: boolean, + numerator: string, + denominator: string, + fixedFeeAmount: string, +) => { + return ( + consensusNodeFeeEqualsCustomFee( + customRoyaltyFee, + feeCollectorAccountId, + feeCollectorsExempt, + ) && + numerator === customRoyaltyFee.numerator?.toString() && + denominator === customRoyaltyFee.denominator?.toString() && + fixedFeeAmount === customRoyaltyFee.fallbackFee?.amount?.toString() + ); +}; + +const mirrorNodeFeeEqualsCustomFixedFee = ( + // TODO: Get mirror node interface with OpenAPI + customFixedFee: any, + feeCollectorAccountId: string, + amount: string, +) => { + return ( + feeCollectorAccountId.toString() === + customFixedFee.collector_account_id.toString() && + amount === customFixedFee.amount?.toString() + ); +}; + +const mirrorNodeFeeEqualsCustomFractionalFee = ( + // TODO: Get mirror node interface with OpenAPI + customFractionalFee: any, + feeCollectorAccountId: string, + numerator: string, + denominator: string, + minAmount: string, + maxAmount: string, + assessmentMethod: string, +) => { + return ( + feeCollectorAccountId?.toString() === + customFractionalFee.collector_account_id && + numerator === customFractionalFee.amount.numerator.toString() && + denominator === customFractionalFee.amount.denominator.toString() && + minAmount === customFractionalFee.minimum.toString() && + maxAmount === customFractionalFee.maximum.toString() && + (assessmentMethod === "exclusive") === + customFractionalFee._allCollectorsAreExempt + ); +}; + +const mirrorNodeFeeEqualsCustomRoyaltyFee = ( + // TODO: Get mirror node interface with OpenAPI + customRoyaltyFee: any, + feeCollectorAccountId: string, + numerator: string, + denominator: string, + fixedFeeAmount: string, +) => { + return ( + feeCollectorAccountId.toString() === + customRoyaltyFee.collector_account_id && + numerator === customRoyaltyFee.amount.numerator?.toString() && + denominator === customRoyaltyFee.amount.denominator?.toString() && + fixedFeeAmount === customRoyaltyFee.fallback_fee.amount?.toString() + ); +}; + +export const verifyTokenCreationWithFixedFee = async ( + tokenId: string, + feeCollectorAccountId: string, + feeCollectorsExempt: boolean, + amount: string, +) => { + const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); + const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId); + + let foundConsensusNodeFee = false; + let foundMirrorNodeFee = false; + + for (let i = 0; i < consensusNodeInfo.customFees.length; i++) { + if ( + consensusNodeInfo.customFees[i] instanceof CustomFixedFee && + consensusNodeFeeEqualsCustomFixedFee( + consensusNodeInfo.customFees[i] as CustomFixedFee, + feeCollectorAccountId, + feeCollectorsExempt, + amount, + ) + ) { + foundConsensusNodeFee = true; + break; + } + } + + for (let i = 0; i < mirrorNodeInfo.custom_fees.fixed_fees.length; i++) { + if ( + mirrorNodeFeeEqualsCustomFixedFee( + mirrorNodeInfo.custom_fees.fixed_fees[i], + feeCollectorAccountId, + amount, + ) + ) { + foundMirrorNodeFee = true; + break; + } + } + + expect(foundConsensusNodeFee).to.be.true; + expect(foundMirrorNodeFee).to.be.true; +}; + +export const verifyTokenCreationWithFractionalFee = async ( + tokenId: string, + feeCollectorAccountId: string, + feeCollectorsExempt: boolean, + numerator: string, + denominator: string, + minAmount: string, + maxAmount: string, + assessmentMethod: string, +) => { + const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); + const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId); + + let foundConsensusNodeFee = false; + let foundMirrorNodeFee = false; + + for (let i = 0; i < consensusNodeInfo.customFees.length; i++) { + if ( + consensusNodeInfo.customFees[i] instanceof CustomFractionalFee && + consensusNodeFeeEqualsCustomFractionalFee( + consensusNodeInfo.customFees[i] as CustomFractionalFee, + feeCollectorAccountId, + feeCollectorsExempt, + numerator, + denominator, + minAmount, + maxAmount, + assessmentMethod, + ) + ) { + foundConsensusNodeFee = true; + break; + } + } + + for (let i = 0; i < mirrorNodeInfo.custom_fees.fractional_fees.length; 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; +}; + +export const verifyTokenCreationWithRoyaltyFee = async ( + tokenId: string, + feeCollectorAccountId: string, + feeCollectorsExempt: boolean, + numerator: string, + denominator: string, + fixedFeeAmount: string, +) => { + const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); + const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId); + + let foundConsensusNodeFee = false; + let foundMirrorNodeFee = false; + + for (let i = 0; i < consensusNodeInfo.customFees.length; i++) { + if ( + consensusNodeInfo.customFees[i] instanceof CustomRoyaltyFee && + consensusNodeFeeEqualsCustomRoyaltyFee( + consensusNodeInfo.customFees[i] as CustomRoyaltyFee, + feeCollectorAccountId, + feeCollectorsExempt, + numerator, + denominator, + fixedFeeAmount, + ) + ) { + foundConsensusNodeFee = true; + break; + } + } + + for (let i = 0; i < mirrorNodeInfo.custom_fees.royalty_fees.length; i++) { + if ( + mirrorNodeFeeEqualsCustomRoyaltyFee( + mirrorNodeInfo.custom_fees.royalty_fees[i], + feeCollectorAccountId, + numerator, + denominator, + fixedFeeAmount, + ) + ) { + foundMirrorNodeFee = true; + break; + } + } + + expect(foundConsensusNodeFee).to.be.true; + expect(foundMirrorNodeFee).to.be.true; +}; diff --git a/src/utils/helpers/fetch-data.ts b/src/utils/helpers/fetch-data.ts new file mode 100644 index 0000000..b294521 --- /dev/null +++ b/src/utils/helpers/fetch-data.ts @@ -0,0 +1,9 @@ +import axios from "axios"; + +export const fetchData = async (url: string): Promise => { + const response = await axios.get(url); + if (response.data) { + return response.data; + } + throw new Error("No data received"); +}; diff --git a/utils/helpers/key.js b/src/utils/helpers/key.ts similarity index 73% rename from utils/helpers/key.js rename to src/utils/helpers/key.ts index 578a4e3..1831b19 100644 --- a/utils/helpers/key.js +++ b/src/utils/helpers/key.ts @@ -1,8 +1,9 @@ import { proto } from "@hashgraph/proto"; +import { PublicKey } from "@hashgraph/sdk"; -import mirrorNodeClient from "../../mirrorNodeClient.js"; -import consensusInfoClient from "../../consensusInfoClient.js"; -import { keyTypeConvertFunctions } from "./constants/key-type.js"; +import mirrorNodeClient from "@services/MirrorNodeClient"; +import consensusInfoClient from "@services/ConsensusInfoClient"; +import { keyTypeConvertFunctions } from "@constants/key-type"; /** * Retrieves the encoded hexadecimal representation of a specified dynamic key @@ -16,12 +17,16 @@ import { keyTypeConvertFunctions } from "./constants/key-type.js"; * @returns {Promise} - A promise that resolves to the hexadecimal representation of the encoded key. */ export const getEncodedKeyHexFromKeyListConsensus = async ( - consensusInfoClientMethod, - searchedId, - searchedKey, -) => { + consensusInfoClientMethod: keyof typeof consensusInfoClient, + searchedId: string, + searchedKey: string, +): Promise => { // Retrieve the desired data from consensus - const data = await consensusInfoClient[consensusInfoClientMethod](searchedId); + const data = await ( + consensusInfoClient[consensusInfoClientMethod] as ( + id: string, + ) => Promise + )(searchedId); const protoKey = data[searchedKey]._toProtobufKey(); let encodedKeyList; @@ -47,10 +52,10 @@ export const getEncodedKeyHexFromKeyListConsensus = async ( * @returns {Promise} - A promise that resolves to the public key object retrieved from the Mirror Node. */ export const getPublicKeyFromMirrorNode = async ( - mirrorClientMethod, - searchedId, - searchedKey, -) => { + mirrorClientMethod: keyof typeof mirrorNodeClient, + searchedId: string, + searchedKey: string, +): Promise => { // Retrieve the desired data from Mirror node const data = await mirrorNodeClient[mirrorClientMethod](searchedId); @@ -62,9 +67,9 @@ export const getPublicKeyFromMirrorNode = async ( } // Use the appropriate key type function to convert the key - const publicKeyMirrorNode = keyTypeConvertFunctions[keyMirrorNode._type]( - keyMirrorNode.key, - ); + const publicKeyMirrorNode = keyTypeConvertFunctions[ + keyMirrorNode._type as keyof typeof keyTypeConvertFunctions + ](keyMirrorNode.key); return publicKeyMirrorNode; }; diff --git a/utils/helpers/retry-on-error.js b/src/utils/helpers/retry-on-error.ts similarity index 79% rename from utils/helpers/retry-on-error.js rename to src/utils/helpers/retry-on-error.ts index bff58a3..be6d6f4 100644 --- a/utils/helpers/retry-on-error.js +++ b/src/utils/helpers/retry-on-error.ts @@ -10,14 +10,17 @@ * @returns {Promise} A Promise that resolves if the function succeeds within the maximum retries, * or rejects with the last error if all retries fail. */ -export const retryOnError = async (fn, maxRetries = 10, retryDelay = 200) => { +export const retryOnError = async ( + fn: () => Promise, + maxRetries: number = 10, + retryDelay: number = 200, +): Promise => { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { - await fn(); - return; + return await fn(); } catch (error) { if (attempt === maxRetries) { - throw error; + throw error; // Throw the last error if retries are exhausted } // Delay before retrying diff --git a/setup_Tests.js b/src/utils/helpers/setup-tests.ts similarity index 54% rename from setup_Tests.js rename to src/utils/helpers/setup-tests.ts index b380a8a..bf617d0 100644 --- a/setup_Tests.js +++ b/src/utils/helpers/setup-tests.ts @@ -1,12 +1,16 @@ -import { JSONRPCRequest } from "./client.js"; +import { JSONRPCRequest } from "@services/Client"; -export async function setOperator(accountId, privateKey) { +export const setOperator = async ( + mochaTestContext: any, + accountId: string, + privateKey: string, +) => { // sets funding and fee-paying account for CRUD ops - await JSONRPCRequest(this, "setup", { + await JSONRPCRequest(mochaTestContext, "setup", { operatorAccountId: accountId, operatorPrivateKey: privateKey, nodeIp: process.env.NODE_IP, nodeAccountId: process.env.NODE_ACCOUNT_ID, mirrorNetworkIp: process.env.MIRROR_NETWORK, }); -} +}; diff --git a/utils/helpers/token.js b/src/utils/helpers/token.ts similarity index 81% rename from utils/helpers/token.js rename to src/utils/helpers/token.ts index 13e487e..d8006e6 100644 --- a/utils/helpers/token.js +++ b/src/utils/helpers/token.ts @@ -1,8 +1,8 @@ import { expect } from "chai"; -import consensusInfoClient from "../../consensusInfoClient.js"; -import mirrorNodeClient from "../../mirrorNodeClient.js"; -import { JSONRPCRequest } from "../../client.js"; +import consensusInfoClient from "@services/ConsensusInfoClient"; +import mirrorNodeClient from "@services/MirrorNodeClient"; +import { JSONRPCRequest } from "@services/Client"; /** * Verifies that a token has been deleted by checking both the Consensus Info @@ -12,7 +12,7 @@ import { JSONRPCRequest } from "../../client.js"; * @param {string} tokenId - The ID of the token to verify. * @throws {Error} Will throw an error if the token is not marked as deleted in either Consensus Info or Mirror Node. */ -export const verifyTokenIsDeleted = async (tokenId) => { +export const verifyTokenIsDeleted = async (tokenId: string) => { expect(await (await consensusInfoClient.getTokenInfo(tokenId)).isDeleted).to .be.true; @@ -29,10 +29,10 @@ export const verifyTokenIsDeleted = async (tokenId) => { * @returns {Promise} - The ID of the newly created fungible token. */ export const getNewFungibleTokenId = async ( - mochaTestContext, - adminKey, - treasuryAccountId, -) => { + mochaTestContext: any, + adminKey?: string, + treasuryAccountId?: string, +): Promise => { const tokenResponse = await JSONRPCRequest(mochaTestContext, "createToken", { name: "testname", symbol: "testsymbol", diff --git a/utils/helpers/verify-token-tx.js b/src/utils/helpers/verify-token-tx.ts similarity index 65% rename from utils/helpers/verify-token-tx.js rename to src/utils/helpers/verify-token-tx.ts index 081aeb3..effce8f 100644 --- a/utils/helpers/verify-token-tx.js +++ b/src/utils/helpers/verify-token-tx.ts @@ -1,24 +1,28 @@ import { expect } from "chai"; -import { Timestamp } from "@hashgraph/sdk"; +import { Timestamp, TokenInfo, PublicKey } from "@hashgraph/sdk"; -import { getRawKeyFromHex } from "./asn1-decoder.js"; +import { getRawKeyFromHex } from "@helpers/asn1-decoder"; import { getPublicKeyFromMirrorNode, getEncodedKeyHexFromKeyListConsensus, -} from "./key.js"; +} from "@helpers/key"; -import mirrorNodeClient from "../../mirrorNodeClient.js"; -import consensusInfoClient from "../../consensusInfoClient.js"; +import mirrorNodeClient from "@services/MirrorNodeClient"; +import consensusInfoClient from "@services/ConsensusInfoClient"; -export async function verifyTokenKey(tokenId, key, keyType) { +export const verifyTokenKey = async ( + tokenId: string, + key: string, + keyType: string, +) => { const rawKey = getRawKeyFromHex(key); // Fetch the token info from the consensus node const tokenInfo = await consensusInfoClient.getTokenInfo(tokenId); - const tokenKey = tokenInfo[keyType]; + const tokenKey = tokenInfo[keyType as keyof TokenInfo] as PublicKey; // Check if the key matches - expect(rawKey).to.equal(tokenKey.toStringRaw()); + expect(rawKey).to.equal(tokenKey?.toStringRaw()); const mirrorNodeKey = transformConsensusToMirrorNodeProp(keyType); // Fetch the key from the mirror node @@ -29,10 +33,14 @@ export async function verifyTokenKey(tokenId, key, keyType) { ); // Verify that the key from the mirror node matches the raw key - expect(rawKey).to.equal(publicKeyMirrorNode.toStringRaw()); -} - -export async function verifyTokenKeyList(tokenId, key, keyType) { + expect(rawKey).to.equal(publicKeyMirrorNode?.toStringRaw()); +}; + +export const verifyTokenKeyList = async ( + tokenId: string, + key: string, + keyType: string, +) => { // Fetch the encoded key from the consensus node const keyHex = await getEncodedKeyHexFromKeyListConsensus( "getTokenInfo", @@ -46,28 +54,29 @@ export async function verifyTokenKeyList(tokenId, key, keyType) { const mirrorNodeKeyName = transformConsensusToMirrorNodeProp(keyType); // Mirror node check - const mirrorNodeKey = ( - await ( - await mirrorNodeClient.getTokenData(tokenId) - )[mirrorNodeKeyName] - ).key; + const mirrorNodeKey = await ( + await mirrorNodeClient.getTokenData(tokenId) + )[mirrorNodeKeyName].key; // Verify that the key from the mirror node matches the expected key expect(key).to.equal( // Removing the unnecessary prefix from the mirror node key mirrorNodeKey.slice(mirrorNodeKey.length - key.length), ); -} +}; -function transformConsensusToMirrorNodeProp(key) { +const transformConsensusToMirrorNodeProp = (key: string) => { return key.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase(); -} +}; -export async function verifyTokenUpdateWithNullKey(tokenId, keyType) { +export const verifyTokenUpdateWithNullKey = async ( + tokenId: string, + keyType: string, +) => { // Fetch the key from the consensus node and check if it is null - const consensusNodeKey = await ( - await consensusInfoClient.getTokenInfo(tokenId) - )[keyType]; + const consensusNodeKey = (await consensusInfoClient.getTokenInfo(tokenId))[ + keyType as keyof TokenInfo + ]; expect(null).to.equal(consensusNodeKey); // Convert the keyType to match the mirror node property format @@ -80,17 +89,18 @@ export async function verifyTokenUpdateWithNullKey(tokenId, keyType) { mirrorNodeKeyName, ); expect(null).to.equal(mirrorNodeKey); -} +}; -export async function verifyTokenExpirationTimeUpdate(tokenId, expirationTime) { +export const verifyTokenExpirationTimeUpdate = async ( + tokenId: string, + expirationTime: string, +) => { const parsedExpirationTime = Timestamp.fromDate( new Date(Number(expirationTime) * 1000), ); expect(parsedExpirationTime).to.deep.equal( - await ( - await consensusInfoClient.getTokenInfo(tokenId) - ).expirationTime, + (await consensusInfoClient.getTokenInfo(tokenId)).expirationTime, ); const mirrorNodeExpirationDateNanoseconds = await ( @@ -103,4 +113,4 @@ export async function verifyTokenExpirationTimeUpdate(tokenId, expirationTime) { ); expect(parsedExpirationTime).to.deep.equal(mirrorNodeTimestamp); -} +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c92b1cc --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2021", + "module": "CommonJS", + "strict": true, + "esModuleInterop": true, + "outDir": "./dist", + "rootDir": "./src", + "moduleResolution": "Node", + "resolveJsonModule": true, + "skipLibCheck": true, + "baseUrl": "./", + "paths": { + "@helpers/*": ["src/utils/helpers/*"], + "@services/*": ["src/services/*"], + "@constants/*": ["src/utils/helpers/constants/*"] + } + }, + "include": ["src/**/*.ts", "src/tests/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/utils/helpers/custom-fees.js b/utils/helpers/custom-fees.js deleted file mode 100644 index 6b054c6..0000000 --- a/utils/helpers/custom-fees.js +++ /dev/null @@ -1,275 +0,0 @@ -import { expect } from "chai"; -import { - CustomFixedFee, - CustomFractionalFee, - CustomRoyaltyFee, -} from "@hashgraph/sdk"; - -import mirrorNodeClient from "../../mirrorNodeClient.js"; -import consensusInfoClient from "../../consensusInfoClient.js"; - -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 - ); -} - -export async function verifyTokenCreationWithFixedFee( - tokenId, - feeCollectorAccountId, - feeCollectorsExempt, - amount, -) { - const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); - const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId); - - let foundConsensusNodeFee = false; - let foundMirrorNodeFee = false; - - for (let i = 0; i < consensusNodeInfo.customFees.length; 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.length; i++) { - if ( - mirrorNodeFeeEqualsCustomFixedFee( - mirrorNodeInfo.custom_fees.fixed_fees[i], - feeCollectorAccountId, - amount, - ) - ) { - foundMirrorNodeFee = true; - break; - } - } - - expect(foundConsensusNodeFee).to.be.true; - expect(foundMirrorNodeFee).to.be.true; -} - -export async function verifyTokenCreationWithFractionalFee( - tokenId, - feeCollectorAccountId, - feeCollectorsExempt, - numerator, - denominator, - minAmount, - maxAmount, - assessmentMethod, -) { - const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); - const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId); - - let foundConsensusNodeFee = false; - let foundMirrorNodeFee = false; - - for (let i = 0; i < consensusNodeInfo.customFees.length; 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.length; 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; -} - -export async function verifyTokenCreationWithRoyaltyFee( - tokenId, - feeCollectorAccountId, - feeCollectorsExempt, - numerator, - denominator, - fixedFeeAmount, -) { - const consensusNodeInfo = await consensusInfoClient.getTokenInfo(tokenId); - const mirrorNodeInfo = await mirrorNodeClient.getTokenData(tokenId); - - let foundConsensusNodeFee = false; - let foundMirrorNodeFee = false; - - for (let i = 0; i < consensusNodeInfo.customFees.length; 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.royalty_fees.length; i++) { - if ( - mirrorNodeFeeEqualsCustomRoyaltyFee( - mirrorNodeInfo.custom_fees.royalty_fees[i], - feeCollectorAccountId, - numerator, - denominator, - fixedFeeAmount, - ) - ) { - foundMirrorNodeFee = true; - break; - } - } - - expect(foundConsensusNodeFee).to.be.true; - expect(foundMirrorNodeFee).to.be.true; -} From e9d740117ca53ef8983caacec1d6ea65e68bc358 Mon Sep 17 00:00:00 2001 From: Rob Walworth <110835868+rwalworth@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:45:23 -0500 Subject: [PATCH 12/12] docs: Add test specifications for `TokenMintTransaction` (#271) Signed-off-by: Rob Walworth --- .../token-service/tokenMintTransaction.md | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 test-specifications/token-service/tokenMintTransaction.md diff --git a/test-specifications/token-service/tokenMintTransaction.md b/test-specifications/token-service/tokenMintTransaction.md new file mode 100644 index 0000000..074e406 --- /dev/null +++ b/test-specifications/token-service/tokenMintTransaction.md @@ -0,0 +1,202 @@ +# TokenMintTransaction - Test specification + +## Description: +This test specification for TokenMintTransaction is to be one of many for testing the functionality of the Hedera SDKs. The SDK under test will use the language specific JSON-RPC server return responses back to the test driver. + +## Design: +Each test within the test specification is linked to one of the properties within TokenMintTransaction. Each property is tested with a mix of boundaries. The inputs for each test are a range of valid, minimum, maximum, negative and invalid values for the method. The expected response of a passed test can be a correct error response code or seen as the result of node queries. A successful transaction (the transaction reached consensus and was applied to state) can be determined by getting a `TransactionReceipt` or `TransactionRecord`, or can be determined by using queries such as `TokenInfoQuery` or `AccountBalanceQuery` and investigating for the required changes (creations, updates, etc.). The mirror node can also be used to determine if a transaction was successful via its rest API. Error codes are obtained from the response code proto files. + +**Transaction properties:** + +https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/mint-a-token + +**TokenMint protobufs:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/token_mint.proto + +**Response codes:** + +https://github.com/hashgraph/hedera-protobufs/blob/main/services/response_code.proto + +**Mirror Node APIs:** + +https://docs.hedera.com/hedera/sdks-and-apis/rest-api + +## JSON-RPC API Endpoint Documentation + +### Method Name + +`mintToken` + +### Input Parameters + +| Parameter Name | Type | Required/Optional | Description/Notes | +|-------------------------|--------------------------------------------------|-------------------|-------------------------------------------------------------------| +| tokenId | string | optional | The ID of the token to mint. | +| amount | string | optional | The amount of fungible tokens to mint. | +| metadata | list | optional | The metadata for the non-fungible tokens to mint, as hex strings. | +| commonTransactionParams | [json object](../commonTransactionParameters.md) | optional | | + +### Output Parameters + +| Parameter Name | Type | Required/Optional | Description/Notes | +|----------------|--------------|-------------------|-----------------------------------------------------------------------------------| +| status | string | required | The status of the submitted `TokenMintTransaction` (from a `TransactionReceipt`). | +| newTotalSupply | string | required | The new total amount of tokens. | +| serialNumbers | list | optional | When minting NFTs, the serial numbers of the minted NFTs. | + +### Additional Notes + +The tests contained in this specification will assume that a valid fungible token and a valid non-fungible token have already successfully created. The fungible token should be created with 0 decimals. will denote the ID of the created fungible token, will denote the supply key of the created fungible token as a DER-encoded hex string, and will denote the admin key of the created fungible token as a DER-encoded hex string. will denote the ID of the created non-fungible token, will denote the supply key of the created non-fungible token as a DER-encoded hex string, and will denote the admin key of the created non-fungible token as a DER-encoded hex string. + +## Property Tests + +### **Token ID:** + +- The ID of the token to mint. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|-----------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|-------------------| +| 1 | Mints a valid amount of fungible token | tokenId=, amount="10", commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains the minted tokens. | N | +| 2 | Mints a valid non-fungible token | tokenId=, metadata=["1234"], commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains the minted NFT. | N | +| 3 | Mints a token with an empty token ID | tokenId="" | The token mint fails with an SDK internal error. | N | +| 4 | Mints a token with no token ID | | The token mint fails with an INVALID_TOKEN_ID response code from the network. | N | +| 5 | Mints a deleted token | tokenId=, commonTransactionParams.signers=[] | The token mint fails with an TOKEN_WAS_DELETED response code from the network. | N | +| 6 | Mints a token without signing with the token's supply key | tokenId=, amount="10" | The token mint fails with an INVALID_SIGNATURE response code from the network. | N | +| 7 | Mints a token but signs with the token's admin key | tokenId=, amount="10", commonTransactionParams.signers=[] | The token mint fails with an INVALID_SIGNATURE response code from the network. | N | +| 8 | Mints a token but signs with an incorrect supply key | tokenId=, amount="10" commonTransactionParams.signers=[] | The token mint fails with an INVALID_SIGNATURE response code from the network. | N | +| 9 | Mints a token with no supply key | tokenId=, amount="10" | The token mint fails with an TOKEN_HAS_NO_SUPPLY_KEY response code from the network. | N | +| 10 | Mints a paused token | tokenId=, amount="10", commonTransactionParams.signers=[] | The token mint fails with an TOKEN_IS_PAUSED response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "method": "mintToken", + "params": { + "tokenId": "0.0.15432", + "amount": "1000" + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "result": { + "status": "SUCCESS", + "newTotalSupply": "1001000" + } +} +``` + +### **Amount:** + +- The amount of fungible tokens to mint. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|--------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|-------------------| +| 1 | Mints an amount of 1,000,000 fungible tokens | tokenId=, amount="1000000", commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains 1,000,000 more minted tokens. | N | +| 2 | Mints an amount of 0 fungible tokens | tokenId=, amount="0", commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains 0 more minted tokens. | N | +| 3 | Mints no fungible tokens | tokenId=, commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains 0 more minted tokens. | N | +| 4 | Mints an amount of 9,223,372,036,854,775,806 (int64 max - 1) fungible tokens | tokenId=, amount="9223372036854775806", commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains 9,223,372,036,854,775,806 more minted tokens. | N | +| 5 | Mints an amount of 9,223,372,036,854,775,807 (int64 max) fungible tokens | tokenId=, amount="9223372036854775807", commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains 9,223,372,036,854,775,807 more minted tokens. | N | +| 6 | Mints an amount of 9,223,372,036,854,775,808 (int64 max + 1) fungible tokens | tokenId=, amount="9223372036854775808", commonTransactionParams.signers=[] | The token mint fails with an INVALID_TOKEN_MINT_AMOUNT response code from the network. | N | +| 7 | Mints an amount of 18,446,744,073,709,551,614 (uint64 max - 1) fungible tokens | tokenId=, amount="18446744073709551614", commonTransactionParams.signers=[] | The token mint fails with an INVALID_TOKEN_MINT_AMOUNT response code from the network. | N | +| 8 | Mints an amount of 18,446,744,073,709,551,615 (uint64 max) fungible tokens | tokenId=, amount="18446744073709551615", commonTransactionParams.signers=[] | The token mint fails with an INVALID_TOKEN_MINT_AMOUNT response code from the network. | N | +| 9 | Mints an amount of 10,000 fungible tokens with 2 decimals | tokenId=, amount="10000", commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains 100 more minted tokens. | N | +| 10 | Mints an amount of 10,000 fungible tokens with 1,000 max supply | tokenId=, amount="10000", commonTransactionParams.signers=[] | The token mint fails with an INVALID_TOKEN_MINT_AMOUNT response code from the network. | N | +| 11 | Mints fungible tokens with the treasury account frozen | tokenId=, amount="1000000", commonTransactionParams.signers=[] | The token mint fails with an ACCOUNT_FROZEN_FOR_TOKEN response code from the network. | N | +| 12 | Mints paused fungible tokens | tokenId=, amount="1000000", commonTransactionParams.signers=[] | The token mint fails with an TOKEN_IS_PAUSED response code from the network. | N | +| 13 | Mints an amount of 1,000,000 NFTs | tokenId=, amount="1000000", commonTransactionParams.signers=[] | The token mint fails with an INVALID_TOKEN_MINT_METADATA response code from the network. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "method": "mintToken", + "params": { + "tokenId": "0.0.15432", + "amount": "1000000", + "commonTransactionParams": { + "signers": [ + "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "result": { + "status": "SUCCESS", + "newTotalSupply": "2000000" + } +} +``` + + +### **Metadata:** + +- The metadata for each NFT to be minted. + +| Test no | Name | Input | Expected response | Implemented (Y/N) | +|---------|---------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------|-------------------| +| 1 | Mints an NFT | tokenId=, metadata=["1234"], commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains an NFT with metadata "1234". | N | +| 2 | Mints an NFT with empty metadata | tokenId=, metadata=[""], commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains an NFT with no metadata. | N | +| 3 | Mints an NFT with non-ASCII metadata | tokenId=, metadata=["𝐭𝐞𝐬𝐭𝐝𝐚𝐭𝐚"], commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains an NFT with metadata "𝐭𝐞𝐬𝐭𝐝𝐚𝐭𝐚". | N | +| 4 | Mints 3 NFTs | tokenId=, metadata=["1234", "5678", "90ab"], commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains 3 NFTs with the input metadata. | N | +| 5 | Mints no NFTs | tokenId=, commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains 0 more NFTs. | N | +| 6 | Mints an amount of 3 NFTs with 1 max supply | tokenId=, metadata=["1234", "5678", "90ab"], commonTransactionParams.signers=[] | The token mint fails with an TOKEN_MAX_SUPPLY_REACHED response code from the network. | N | +| 7 | Mints NFTs with the treasury account frozen | tokenId=, amount="1000000", commonTransactionParams.signers=[] | The token mint fails with an ACCOUNT_FROZEN_FOR_TOKEN response code from the network. | N | +| 8 | Mints paused NFTs | tokenId=, metadata=["1234"], commonTransactionParams.signers=[] | The token mint fails with an TOKEN_IS_PAUSED response code from the network. | N | +| 9 | Mints fungible tokens with metadata | tokenId=, metadata=["1234"], commonTransactionParams.signers=[] | The token mint succeeds and the token's treasury account contains 0 more minted tokens. | N | + +#### JSON Request Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "method": "mintToken", + "params": { + "tokenId": "0.0.15432", + "metadata": [ + "1234" + ], + "commonTransactionParams": { + "signers": [ + "302E020100300506032B657004220420DE6788D0A09F20DED806F446C02FB929D8CD8D17022374AFB3739A1D50BA72C8" + ] + } + } +} +``` + +#### JSON Response Example + +```json +{ + "jsonrpc": "2.0", + "id": 64362, + "result": { + "status": "SUCCESS", + "newTotalSupply": "1", + "serialNumbers": [ + "1" + ] + } +} +```