>> This comment is special code for setting PBJ Compiler java package
18 | option java_multiple_files = true;
19 |
20 | /**
21 | * A transaction body for sending the public TSS encryption key.
22 | */
23 | message TssEncryptionKeyTransactionBody {
24 | /**
25 | * The raw bytes of the public TSS encryption key of the node sending the transaction.
26 | *
27 | * This value MUST be set.
28 | * This value MUST NOT be empty.
29 | */
30 | bytes publicTssEncryptionKey = 1;
31 | }
32 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/services/consensus_delete_topic.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * # Delete Topic
3 | * Delete an existing topic from the Hedera Consensus Service (HCS).
4 | *
5 | * ### Keywords
6 | * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
7 | * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
8 | * document are to be interpreted as described in
9 | * [RFC2119](https://www.ietf.org/rfc/rfc2119) and clarified in
10 | * [RFC8174](https://www.ietf.org/rfc/rfc8174).
11 | */
12 | syntax = "proto3";
13 |
14 | package proto;
15 |
16 | // SPDX-License-Identifier: Apache-2.0
17 | option java_package = "com.hederahashgraph.api.proto.java";
18 | // <<>> This comment is special code for setting PBJ Compiler java package
19 | option java_multiple_files = true;
20 |
21 | import "services/basic_types.proto";
22 |
23 | /**
24 | * Delete a topic.
25 | *
26 | * Once deleted, subsequent transactions or queries for that topic SHALL NOT
27 | * succeed.
28 | * If adminKey is set on the topic, this transaction MUST be signed by that
29 | * key.
30 | * If adminKey is not set on the topic, this transaction SHALL fail with a
31 | * response code of `UNAUTHORIZED`. A topic without an adminKey cannot be
32 | * deleted (but MAY expire).
33 | *
34 | * ### Block Stream Effects
35 | * None
36 | */
37 | message ConsensusDeleteTopicTransactionBody {
38 | /**
39 | * Topic to be deleted.
40 | */
41 | TopicID topicID = 1;
42 | }
43 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/services/crypto_delete_live_hash.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * # Delete Live Hash
3 | * Dissociate a specific live hash from a specified account.
4 | *
5 | * > Important
6 | * >> This transaction is obsolete and not supported.
7 | * >> Any transaction of this type that is submitted SHALL fail with a `PRE_CHECK` result
8 | * >> of `NOT_SUPPORTED`.
9 | *
10 | * ### Keywords
11 | * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
12 | * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
13 | * document are to be interpreted as described in
14 | * [RFC2119](https://www.ietf.org/rfc/rfc2119) and clarified in
15 | * [RFC8174](https://www.ietf.org/rfc/rfc8174).
16 | */
17 | syntax = "proto3";
18 |
19 | package proto;
20 |
21 | // SPDX-License-Identifier: Apache-2.0
22 | option java_package = "com.hederahashgraph.api.proto.java";
23 | // <<>> This comment is special code for setting PBJ Compiler java package
24 | option java_multiple_files = true;
25 |
26 | import "services/basic_types.proto";
27 |
28 | /**
29 | * Delete a specific live hash associated to a given account.
30 | *
31 | * This transaction MUST be signed by either the key of the associated account,
32 | * or at least one of the keys listed in the live hash.
33 | *
34 | * ### Block Stream Effects
35 | * None
36 | */
37 | message CryptoDeleteLiveHashTransactionBody {
38 | /**
39 | * An account associated to a live hash.
40 | */
41 | AccountID accountOfLiveHash = 1;
42 |
43 | /**
44 | * The SHA-384 value of a specific live hash to delete.
45 | */
46 | bytes liveHashToDelete = 2;
47 | }
48 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/services/duration.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * # Duration
3 | * A duration, in seconds.
4 | *
5 | * ### Keywords
6 | * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
7 | * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
8 | * document are to be interpreted as described in
9 | * [RFC2119](https://www.ietf.org/rfc/rfc2119) and clarified in
10 | * [RFC8174](https://www.ietf.org/rfc/rfc8174).
11 | */
12 | syntax = "proto3";
13 |
14 | package proto;
15 |
16 | // SPDX-License-Identifier: Apache-2.0
17 | option java_package = "com.hederahashgraph.api.proto.java";
18 | // <<>> This comment is special code for setting PBJ Compiler java package
19 | option java_multiple_files = true;
20 |
21 | /**
22 | * A length of time in seconds.
23 | *
24 | * It is RECOMMENDED that this message be used whenever an amount of time,
25 | * rather than a specific point in time, is needed.
26 | */
27 | message Duration {
28 | /**
29 | * The number of seconds for this duration.
30 | */
31 | int64 seconds = 1;
32 | }
33 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/services/node_delete.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package com.hedera.hapi.node.addressbook;
4 |
5 | // SPDX-License-Identifier: Apache-2.0
6 | option java_package = "com.hederahashgraph.api.proto.java";
7 | // <<>> This comment is special code for setting PBJ Compiler java package
8 | option java_multiple_files = true;
9 |
10 | /**
11 | * A transaction body to delete a node from the network address book.
12 | *
13 | * - A `NodeDeleteTransactionBody` MUST be signed by one of those keys:
14 | * adminKey, treasure account (2) key, systemAdmin(50) key, or
15 | * addressBookAdmin(55) key.
16 | * - Upon success, the address book entry SHALL enter a "pending delete"
17 | * state.
18 | * - All address book entries pending deletion SHALL be removed from the
19 | * active network configuration during the next `freeze` transaction with
20 | * the field `freeze_type` set to `PREPARE_UPGRADE`.
21 | * - A deleted address book node SHALL be removed entirely from network state.
22 | * - A deleted address book node identifier SHALL NOT be reused.
23 | *
24 | * ### Block Stream Effects
25 | * None.
26 | */
27 | message NodeDeleteTransactionBody {
28 | /**
29 | * A consensus node identifier in the network state.
30 | *
31 | * The node identified MUST exist in the network address book.
32 | * The node identified MUST NOT be deleted.
33 | * This value is REQUIRED.
34 | */
35 | uint64 node_id = 1;
36 | }
37 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/services/schedule_delete.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * # Schedule Delete
3 | * A transaction body for a `scheduleDelete` transaction.
4 | *
5 | * ### Keywords
6 | * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
7 | * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
8 | * document are to be interpreted as described in
9 | * [RFC2119](https://www.ietf.org/rfc/rfc2119) and clarified in
10 | * [RFC8174](https://www.ietf.org/rfc/rfc8174).
11 | */
12 | syntax = "proto3";
13 |
14 | package proto;
15 |
16 | // SPDX-License-Identifier: Apache-2.0
17 | option java_package = "com.hederahashgraph.api.proto.java";
18 | // <<>> This comment is special code for setting PBJ Compiler java package
19 | option java_multiple_files = true;
20 |
21 | import "services/basic_types.proto";
22 |
23 | /**
24 | * Mark a schedule in the network state as deleted.
25 | *
26 | * This transaction MUST be signed by the `adminKey` for the
27 | * identified schedule.
28 | * If a schedule does not have `adminKey` set or if `adminKey` is an empty
29 | * `KeyList`, that schedule SHALL be immutable and MUST NOT be deleted.
30 | * A deleted schedule SHALL not be executed.
31 | * A deleted schedule MUST NOT be the subject of a subsequent
32 | * `scheduleSign` transaction.
33 | *
34 | * ### Block Stream Effects
35 | * None
36 | */
37 | message ScheduleDeleteTransactionBody {
38 | /**
39 | * A schedule identifier.
40 | *
41 | * This MUST identify the schedule which SHALL be deleted.
42 | */
43 | ScheduleID scheduleID = 1;
44 | }
45 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/services/state/contract/bytecode.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * # EVM Bytecode
3 | * The verified bytecode of an EVM contract for the Hedera Smart Contract service.
4 | *
5 | * ### Keywords
6 | * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
7 | * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
8 | * document are to be interpreted as described in [RFC2119](https://www.ietf.org/rfc/rfc2119)
9 | * and clarified in [RFC8174](https://www.ietf.org/rfc/rfc8174).
10 | */
11 | syntax = "proto3";
12 |
13 | package proto;
14 |
15 | // SPDX-License-Identifier: Apache-2.0
16 | option java_package = "com.hederahashgraph.api.proto.java";
17 | // <<>> This comment is special code for setting PBJ Compiler java package
18 | option java_multiple_files = true;
19 |
20 | /**
21 | * The bytecode for a contract account.
22 | *
23 | * This is not referred to by any other protocol buffer, but is used internally
24 | * within the Hedera Node software.
25 | */
26 | message Bytecode {
27 | /**
28 | * The raw bytes (not hex-encoded) of a contract's bytecode.
29 | */
30 | bytes code = 1;
31 | }
32 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/services/state/primitives.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * # Primitives
3 | * Primitive value wrapper messages.
4 | *
5 | * These SHALL be used only for situations where the entire value to be stored
6 | * in state is a single primitive. These MUST NOT ever be used as components of
7 | * another message; use the protobuf type instead.
8 | *
9 | * ### Keywords
10 | * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
11 | * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
12 | * document are to be interpreted as described in [RFC2119](https://www.ietf.org/rfc/rfc2119)
13 | * and clarified in [RFC8174](https://www.ietf.org/rfc/rfc8174).
14 | */
15 | syntax = "proto3";
16 |
17 | package proto;
18 |
19 | // SPDX-License-Identifier: Apache-2.0
20 | option java_package = "com.hederahashgraph.api.proto.java";
21 | // <<>> This comment is special code for setting PBJ Compiler java package
22 | option java_multiple_files = true;
23 |
24 | /**
25 | * A single 64-bit number with no particular meaning.
26 | */
27 | message ProtoLong {
28 | int64 value = 1;
29 | }
30 |
31 | /**
32 | * A single 32-bit number with no particular meaning.
33 | */
34 | message ProtoInteger {
35 | int32 value = 1;
36 | }
37 |
38 | /**
39 | * A single boolean with no particular meaning.
40 | */
41 | message ProtoBoolean {
42 | bool value = 1;
43 | }
44 |
45 | /**
46 | * A single string with no particular meaning.
47 | */
48 | message ProtoString {
49 | string value = 1;
50 | }
51 |
52 | /**
53 | * A single byte array with no particular meaning.
54 | */
55 | message ProtoBytes {
56 | bytes value = 1;
57 | }
58 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/services/state/tss/tss_encryption_keys.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * # Current and next TSS encryption keys
3 | *
4 | * ### Keywords
5 | * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
6 | * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
7 | * document are to be interpreted as described in
8 | * [RFC2119](https://www.ietf.org/rfc/rfc2119) and clarified in
9 | * [RFC8174](https://www.ietf.org/rfc/rfc8174).
10 | */
11 | syntax = "proto3";
12 |
13 | package com.hedera.hapi.node.state.tss;
14 |
15 | // SPDX-License-Identifier: Apache-2.0
16 | option java_package = "com.hedera.hapi.node.state.tss.legacy";
17 | // <<>> This comment is special code for setting PBJ Compiler java package
18 | option java_multiple_files = true;
19 |
20 | /**
21 | * A message containing a node's current and next TSS encryption keys, where
22 | * the next key (if present) will be switched to the node's current key during
23 | * the first transaction at the beginning of a staking period.
24 | */
25 | message TssEncryptionKeys {
26 |
27 | /**
28 | * If non-empty, a node's current TSS encryption key.
29 | */
30 | bytes current_encryption_key = 1;
31 |
32 | /**
33 | * If non-empty, the same node's next TSS encryption key.
34 | */
35 | bytes next_encryption_key = 2;
36 | }
37 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/services/state/tss/tss_message_map_key.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * # Tss Message Map Key
3 | *
4 | * ### Keywords
5 | * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
6 | * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
7 | * document are to be interpreted as described in
8 | * [RFC2119](https://www.ietf.org/rfc/rfc2119) and clarified in
9 | * [RFC8174](https://www.ietf.org/rfc/rfc8174).
10 | */
11 | syntax = "proto3";
12 |
13 | package com.hedera.hapi.node.state.tss;
14 |
15 | // SPDX-License-Identifier: Apache-2.0
16 | option java_package = "com.hedera.hapi.node.state.tss.legacy";
17 | // <<>> This comment is special code for setting PBJ Compiler java package
18 | option java_multiple_files = true;
19 |
20 | /**
21 | * A key for use in the Threshold Signature Scheme (TSS) TssMessageMaps.
22 | *
23 | * This key SHALL be used to uniquely identify entries in the Message Maps.
24 | */
25 | message TssMessageMapKey {
26 |
27 | /**
28 | * A hash that uniquely identifies the target roster for the associated value
29 | * in the map.
30 | *
31 | * This value MUST be set.
32 | * This value MUST NOT be empty.
33 | * This value MUST contain a valid hash.
34 | */
35 | bytes roster_hash = 1;
36 |
37 | /**
38 | * A number representing consensus order.
39 | * This declares the order in which the mapped value came to consensus.
40 | *
This value MUST be set.
41 | * This value MUST be a valid sequence number.
42 | */
43 | uint64 sequence_number = 2;
44 | }
45 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/services/state/tss/tss_vote_map_key.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * # Tss Vote Map Key
3 | *
4 | * ### Keywords
5 | * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
6 | * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
7 | * document are to be interpreted as described in
8 | * [RFC2119](https://www.ietf.org/rfc/rfc2119) and clarified in
9 | * [RFC8174](https://www.ietf.org/rfc/rfc8174).
10 | */
11 | syntax = "proto3";
12 |
13 | package com.hedera.hapi.node.state.tss;
14 |
15 | // SPDX-License-Identifier: Apache-2.0
16 | option java_package = "com.hedera.hapi.node.state.tss.legacy";
17 | // <<>> This comment is special code for setting PBJ Compiler java package
18 | option java_multiple_files = true;
19 |
20 | /**
21 | * A key for use in the Threshold Signature Scheme (TSS) TssVoteMaps.
22 | *
23 | * This key SHALL be used to uniquely identify entries in the Vote Maps.
24 | */
25 | message TssVoteMapKey {
26 |
27 | /**
28 | * A hash of the target roster for the associated value in the map.
29 | * This hash uniquely identifies the target roster.
30 | *
31 | * This value MUST be set.
32 | * This value MUST contain a valid hash.
33 | */
34 | bytes roster_hash = 1;
35 |
36 | /** The node id of the node that created the TssVote.
37 | * This id uniquely identifies the node.
38 | *
39 | * This value MUST be set.
40 | * This value MUST be a valid node id.
41 | */
42 | uint64 node_id = 2;
43 | }
44 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/services/util_prng.proto:
--------------------------------------------------------------------------------
1 | /**
2 | * # Utility PRNG query
3 | * A query to retrieve a deterministic pseudo-random value.
4 | *
5 | * ### Keywords
6 | * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
7 | * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
8 | * document are to be interpreted as described in
9 | * [RFC2119](https://www.ietf.org/rfc/rfc2119) and clarified in
10 | * [RFC8174](https://www.ietf.org/rfc/rfc8174).
11 | */
12 | syntax = "proto3";
13 |
14 | package proto;
15 |
16 | // SPDX-License-Identifier: Apache-2.0
17 | option java_package = "com.hederahashgraph.api.proto.java";
18 | // <<>> This comment is special code for setting PBJ Compiler java package
19 | option java_multiple_files = true;
20 |
21 | /**
22 | * Request a deterministic pseudo-random number.
23 | *
24 | * The value returned SHALL be deterministic, but not easily predicted.
25 | * The value returned SHALL NOT be suitable for cryptographic use.
26 | *
27 | * ### Block Stream Effects
28 | * The result of this transaction is reported in a `UtilPrngOutput` message.
29 | */
30 | message UtilPrngTransactionBody {
31 | /**
32 | * A range for the requested value.
33 | *
34 | * If this is greater than `0`, the service SHALL return a 32-bit
35 | * pseudo-random number between 0 and the value provided in the
36 | * transaction record.
37 | * If this is unset, zero, or negative; the service SHALL return a
38 | * 384-bit unsigned pseudo-random number in the record.
39 | */
40 | int32 range = 1;
41 | }
42 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/streams/contract_bytecode.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package proto;
4 |
5 | /*-
6 | *
7 | * Hedera Network Services Protobuf
8 | *
9 | * Copyright (C) 2018 - 2022 Hedera Hashgraph, LLC
10 | *
11 | * Licensed under the Apache License, Version 2.0 (the "License");
12 | * you may not use this file except in compliance with the License.
13 | * You may obtain a copy of the License at
14 | *
15 | * http://www.apache.org/licenses/LICENSE-2.0
16 | *
17 | * Unless required by applicable law or agreed to in writing, software
18 | * distributed under the License is distributed on an "AS IS" BASIS,
19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 | * See the License for the specific language governing permissions and
21 | * limitations under the License.
22 | *
23 | */
24 |
25 | option java_package = "com.hedera.services.stream.proto";
26 | // <<>> This comment is special code for setting PBJ Compiler java package
27 | option java_multiple_files = true;
28 |
29 | import "services/basic_types.proto";
30 |
31 | message ContractBytecode {
32 | /**
33 | * The contract to which the bytecodes apply to
34 | */
35 | ContractID contract_id = 1;
36 |
37 | /**
38 | * Contract bytecode during deployment
39 | */
40 | bytes initcode = 2;
41 |
42 | /**
43 | * Contract bytecode after deployment
44 | */
45 | bytes runtime_bytecode = 3;
46 | }
47 |
--------------------------------------------------------------------------------
/packages/proto/src/proto/streams/hash_object.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package proto;
4 |
5 | /*-
6 | *
7 | * Hedera Network Services Protobuf
8 | *
9 | * Copyright (C) 2018 - 2022 Hedera Hashgraph, LLC
10 | *
11 | * Licensed under the Apache License, Version 2.0 (the "License");
12 | * you may not use this file except in compliance with the License.
13 | * You may obtain a copy of the License at
14 | *
15 | * http://www.apache.org/licenses/LICENSE-2.0
16 | *
17 | * Unless required by applicable law or agreed to in writing, software
18 | * distributed under the License is distributed on an "AS IS" BASIS,
19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 | * See the License for the specific language governing permissions and
21 | * limitations under the License.
22 | *
23 | */
24 |
25 | option java_package = "com.hedera.services.stream.proto";
26 | // <<>> This comment is special code for setting PBJ Compiler java package
27 | option java_multiple_files = true;
28 |
29 | /**
30 | * List of hash algorithms
31 | */
32 | enum HashAlgorithm {
33 | HASH_ALGORITHM_UNKNOWN = 0;
34 | SHA_384 = 1;
35 | }
36 |
37 | /**
38 | * Encapsulates an object hash so that additional hash algorithms
39 | * can be added in the future without requiring a breaking change.
40 | */
41 | message HashObject {
42 |
43 | /**
44 | * Specifies the hashing algorithm
45 | */
46 | HashAlgorithm algorithm = 1;
47 |
48 | /**
49 | * Hash length
50 | */
51 | int32 length = 2;
52 |
53 | /**
54 | * Specifies the result of the hashing operation in bytes
55 | */
56 | bytes hash = 3;
57 | }
58 |
--------------------------------------------------------------------------------
/packages/proto/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "lib": ["ESNext", "DOM"],
6 | "allowJs": true,
7 | "checkJs": false,
8 | "noEmit": true,
9 | "declaration": true,
10 | "rootDir": "src/",
11 | "strict": true,
12 | "noImplicitAny": true,
13 | "noUnusedLocals": true,
14 | "noUnusedParameters": true,
15 | "downlevelIteration": true,
16 | "noImplicitReturns": true,
17 | "noFallthroughCasesInSwitch": true,
18 | "moduleResolution": "node",
19 | "allowSyntheticDefaultImports": true,
20 | "esModuleInterop": true,
21 | "forceConsistentCasingInFileNames": true
22 | },
23 | "include": ["src"],
24 | "exclude": ["src/proto.js"]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/proto/vite.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | optimizeDeps: {
3 | allowNodeBuiltins: [
4 | "@hashgraph/cryptography"
5 | ]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/playwright.config.js:
--------------------------------------------------------------------------------
1 | import { devices } from '@playwright/test';
2 |
3 | /**
4 | * @type {import("@playwright/test").PlaywrightTestConfig}
5 | */
6 | const config = {
7 | forbidOnly: !!process.env.CI,
8 | retries: process.env.CI ? 2 : 0,
9 | use: {
10 | trace: 'on-first-retry',
11 | },
12 | projects: [
13 | {
14 | name: 'chromium',
15 | use: { ...devices['Desktop Chrome'] },
16 | },
17 | {
18 | name: 'firefox',
19 | use: { ...devices['Desktop Firefox'] },
20 | },
21 | ],
22 | };
23 |
24 | if (process.platform === "darwin") {
25 | config.projects.push({
26 | name: 'webkit',
27 | use: { ...devices['Desktop Safari'] },
28 | });
29 | }
30 |
31 | export default config;
32 |
--------------------------------------------------------------------------------
/scripts/update-address-books.js:
--------------------------------------------------------------------------------
1 | import { Client, FileId, AddressBookQuery } from "../src/index.js";
2 |
3 | import fs from "node:fs/promises";
4 |
5 | async function main() {
6 | const networks = [
7 | { name: "previewnet" },
8 | { name: "testnet" },
9 | { name: "mainnet", url: "mainnet-public.mirrornode.hedera.com:443" },
10 | ];
11 |
12 | for (const network of networks) {
13 | const client = Client.forName(network.name, {
14 | scheduleNetworkUpdate: false,
15 | });
16 |
17 | if (network.url != null) {
18 | client.setMirrorNetwork([network.url]).setTransportSecurity(true);
19 | }
20 |
21 | const addressBook = await new AddressBookQuery()
22 | .setFileId(FileId.ADDRESS_BOOK)
23 | .execute(client);
24 |
25 | await fs.writeFile(
26 | `./src/client/addressbooks/${network.name}.js`,
27 | `export const addressBook =
28 | "${Buffer.from(addressBook.toBytes()).toString("hex")}";\n`,
29 | );
30 | }
31 | }
32 |
33 | void main();
34 |
--------------------------------------------------------------------------------
/src/BadEntityIdError.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | export default class BadEntityIdError extends Error {
4 | /**
5 | * @param {Long} shard
6 | * @param {Long} realm
7 | * @param {Long} num
8 | * @param {string} presentChecksum
9 | * @param {string} expectedChecksum
10 | */
11 | constructor(shard, realm, num, presentChecksum, expectedChecksum) {
12 | super(
13 | `Entity ID ${shard.toString()}.${realm.toString()}.${num.toString()}-${presentChecksum} was incorrect.`,
14 | );
15 |
16 | this.name = "BadEntityIdException";
17 |
18 | this.shard = shard;
19 | this.realm = realm;
20 | this.num = num;
21 | this.presentChecksum = presentChecksum;
22 | this.expectedChecksum = expectedChecksum;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Duration.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import Long from "long";
4 |
5 | /**
6 | * @namespace proto
7 | * @typedef {import("@hashgraph/proto").proto.IDuration} HieroProto.proto.IDuration
8 | */
9 |
10 | /**
11 | * A duration type.
12 | *
13 | * The main point of this tyope is for encapsulating the `[to|from]Protobuf()` implementations
14 | */
15 | export default class Duration {
16 | /**
17 | * @param {Long | number} seconds
18 | */
19 | constructor(seconds) {
20 | /**
21 | * @readonly
22 | * @type {Long}
23 | */
24 | this.seconds =
25 | seconds instanceof Long ? seconds : Long.fromNumber(seconds);
26 |
27 | Object.freeze(this);
28 | }
29 |
30 | /**
31 | * @internal
32 | * @returns {HieroProto.proto.IDuration}
33 | */
34 | _toProtobuf() {
35 | return {
36 | seconds: this.seconds,
37 | };
38 | }
39 |
40 | /**
41 | * @internal
42 | * @param {HieroProto.proto.IDuration} duration
43 | * @returns {Duration}
44 | */
45 | static _fromProtobuf(duration) {
46 | return new Duration(/** @type {Long} */ (duration.seconds));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/MaxAttemptsOrTimeoutError.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 | /**
3 | * @typedef {object} MaxAttemptsOrTimeoutErrorJSON
4 | * @property {string} message
5 | * @property {string} nodeAccountId
6 | *
7 | */
8 |
9 | export default class MaxAttemptsOrTimeoutError extends Error {
10 | /**
11 | * @param {string} message
12 | * @param {string} nodeAccountId
13 | */
14 | constructor(message, nodeAccountId) {
15 | // Call the Error constructor with the message
16 | super(message);
17 |
18 | // Assign the nodeAccountId as a custom property
19 | this.nodeAccountId = nodeAccountId;
20 | }
21 |
22 | toJSON() {
23 | return {
24 | message: this.message,
25 | nodeAccountId: this.nodeAccountId,
26 | };
27 | }
28 |
29 | /**
30 | * @returns {string}
31 | */
32 | toString() {
33 | return JSON.stringify(this.toJSON());
34 | }
35 |
36 | /**
37 | * @returns {MaxAttemptsOrTimeoutErrorJSON}
38 | */
39 | valueOf() {
40 | return this.toJSON();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/MaxQueryPaymentExceeded.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * @typedef {import("./Hbar.js").default} Hbar
5 | */
6 |
7 | /**
8 | * Error thrown when a query's cost exceeds the maximum payment amount set on the client.
9 | *
10 | * This error is used to prevent unexpectedly expensive queries from being automatically executed.
11 | * When this error occurs, the user can either:
12 | * 1. Increase the maximum query payment on the client
13 | * 2. Explicitly approve the higher cost for this specific query
14 | */
15 | export default class MaxQueryPaymentExceeded extends Error {
16 | /**
17 | * @param {Hbar} queryCost
18 | * @param {Hbar} maxQueryPayment
19 | */
20 | constructor(queryCost, maxQueryPayment) {
21 | super();
22 |
23 | this.message = `query cost of ${queryCost.toString()} HBAR exceeds max set on client: ${maxQueryPayment.toString()} HBAR`;
24 | this.name = "MaxQueryPaymentExceededError";
25 | this.queryCost = queryCost;
26 | this.maxQueryPayment = maxQueryPayment;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/MirrorNode.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import ManagedNode from "./ManagedNode.js";
4 |
5 | /**
6 | * @typedef {import("./channel/MirrorChannel.js").default} MirrorChannel
7 | * @typedef {import("./ManagedNodeAddress.js").default} ManagedNodeAddress
8 | */
9 |
10 | /**
11 | * @typedef {object} NewNode
12 | * @property {string} address
13 | * @property {(address: string, cert?: string) => MirrorChannel} channelInitFunction
14 | */
15 |
16 | /**
17 | * @typedef {object} CloneNode
18 | * @property {MirrorNode} node
19 | * @property {ManagedNodeAddress} address
20 | */
21 |
22 | /**
23 | * @augments {ManagedNode}
24 | */
25 | export default class MirrorNode extends ManagedNode {
26 | /**
27 | * @param {object} props
28 | * @param {NewNode=} [props.newNode]
29 | * @param {CloneNode=} [props.cloneNode]
30 | */
31 | constructor(props = {}) {
32 | super(props);
33 | }
34 |
35 | /**
36 | * @returns {string}
37 | */
38 | getKey() {
39 | return this._address.toString();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/ReceiptStatusError.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import StatusError from "./StatusError.js";
4 |
5 | /**
6 | * @typedef {import("./Status.js").default} Status
7 | * @typedef {import("./transaction/TransactionId.js").default} TransactionId
8 | * @typedef {import("./transaction/TransactionReceipt.js").default} TransactionReceipt
9 | */
10 |
11 | /**
12 | * Represents an error that occurs when a transaction receipt indicates a failure
13 | * on the Hedera network. The `ReceiptStatusError` class extends the base
14 | * `StatusError` class and provides additional context specific to receipt-related
15 | * failures, such as the transaction ID, status, and any associated messages.
16 | *
17 | * This error is typically thrown when a transaction has been processed, but the
18 | * receipt indicates that it did not complete successfully. It allows developers to
19 | * handle such errors effectively in their applications by providing detailed
20 | * information about the failure.
21 | */
22 | export default class ReceiptStatusError extends StatusError {
23 | /**
24 | * @param {object} props
25 | * @param {TransactionReceipt} props.transactionReceipt
26 | * @param {Status} props.status
27 | * @param {TransactionId} props.transactionId
28 | */
29 | constructor(props) {
30 | super(
31 | props,
32 | `receipt for transaction ${props.transactionId.toString()} contained error status ${props.status.toString()}`,
33 | );
34 |
35 | /**
36 | * @type {TransactionReceipt}
37 | * @readonly
38 | */
39 | this.transactionReceipt = props.transactionReceipt;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/RecordStatusError.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import StatusError from "./StatusError.js";
4 |
5 | /**
6 | * @typedef {import("./Status.js").default} Status
7 | * @typedef {import("./transaction/TransactionId.js").default} TransactionId
8 | * @typedef {import("./transaction/TransactionRecord").default} TransactionRecord
9 | */
10 |
11 | export default class RecordStatusError extends StatusError {
12 | /**
13 | * @param {object} props
14 | * @param {TransactionRecord} props.transactionRecord
15 | * @param {Status} props.status
16 | * @param {TransactionId} props.transactionId
17 | */
18 | constructor(props) {
19 | super(
20 | props,
21 | `Record for transaction ${props.transactionId.toString()} contained error status ${props.status.toString()}`,
22 | );
23 |
24 | /**
25 | * @type {TransactionRecord}
26 | * @readonly
27 | */
28 | this.transactionRecord = props.transactionRecord;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/SignerSignature.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * @typedef {import("./PublicKey.js").default} PublicKey
5 | * @typedef {import("./account/AccountId.js").default} AccountId
6 | */
7 |
8 | /**
9 | * Represents a signature associated with a signer in the Hedera network.
10 | *
11 | * The `SignerSignature` class encapsulates the public key, signature, and account ID
12 | * of a signer. It is used to manage and validate signatures in transactions, ensuring
13 | * that the correct signers are associated with the transaction data.
14 | */
15 | export default class SignerSignature {
16 | /**
17 | * @param {object} props
18 | * @param {PublicKey} props.publicKey
19 | * @param {Uint8Array} props.signature
20 | * @param {AccountId} props.accountId
21 | */
22 | constructor(props) {
23 | this.publicKey = props.publicKey;
24 | this.signature = props.signature;
25 | this.accountId = props.accountId;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/StatusError.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * @typedef {import("./Status.js").default} Status
5 | * @typedef {import("./transaction/TransactionId.js").default} TransactionId
6 | */
7 |
8 | /**
9 | * @typedef {object} StatusErrorJSON
10 | * @property {string} name
11 | * @property {string} status
12 | * @property {string} transactionId
13 | * @property {string} message
14 | */
15 |
16 | export default class StatusError extends Error {
17 | /**
18 | * @param {object} props
19 | * @param {Status} props.status
20 | * @param {TransactionId} props.transactionId
21 | * @param {string} message
22 | */
23 | constructor(props, message) {
24 | super(message);
25 |
26 | this.name = "StatusError";
27 |
28 | this.status = props.status;
29 |
30 | this.transactionId = props.transactionId;
31 |
32 | this.message = message;
33 |
34 | if (typeof Error.captureStackTrace !== "undefined") {
35 | Error.captureStackTrace(this, StatusError);
36 | }
37 | }
38 |
39 | /**
40 | * @returns {StatusErrorJSON}
41 | */
42 | toJSON() {
43 | return {
44 | name: this.name,
45 | status: this.status.toString(),
46 | transactionId: this.transactionId.toString(),
47 | message: this.message,
48 | };
49 | }
50 |
51 | /**
52 | * @returns {string}
53 | */
54 | toString() {
55 | return JSON.stringify(this.toJSON());
56 | }
57 |
58 | /**
59 | * @returns {StatusErrorJSON}
60 | */
61 | valueOf() {
62 | return this.toJSON();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/account/HbarTransferMap.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import AccountId from "./AccountId.js";
4 | import Hbar from "../Hbar.js";
5 | import ObjectMap from "../ObjectMap.js";
6 |
7 | /**
8 | * @namespace proto
9 | * @typedef {import("@hashgraph/proto").proto.ITransferList} HieroProto.proto.ITransferList
10 | * @typedef {import("@hashgraph/proto").proto.IAccountID} HieroProto.proto.IAccountID
11 | */
12 |
13 | /**
14 | * @typedef {import("../long.js").LongObject} LongObject
15 | * @typedef {import("bignumber.js").default} BigNumber
16 | */
17 |
18 | /**
19 | * @augments {ObjectMap}
20 | */
21 | export default class HbarTransferMap extends ObjectMap {
22 | constructor() {
23 | super((s) => AccountId.fromString(s));
24 | }
25 |
26 | /**
27 | * @param {HieroProto.proto.ITransferList} transfers
28 | * @returns {HbarTransferMap}
29 | */
30 | static _fromProtobuf(transfers) {
31 | const accountTransfers = new HbarTransferMap();
32 |
33 | for (const transfer of transfers.accountAmounts != null
34 | ? transfers.accountAmounts
35 | : []) {
36 | const account = AccountId._fromProtobuf(
37 | /** @type {HieroProto.proto.IAccountID} */ (transfer.accountID),
38 | );
39 |
40 | accountTransfers._set(
41 | account,
42 | Hbar.fromTinybars(/** @type {Long} */ (transfer.amount)),
43 | );
44 | }
45 |
46 | return accountTransfers;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/account/NullableTokenDecimalMap.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import TokenId from "../token/TokenId.js";
4 | import ObjectMap from "../ObjectMap.js";
5 |
6 | /**
7 | * @namespace proto
8 | * @typedef {import("@hashgraph/proto").proto.ITokenBalance} HieroProto.proto.ITokenBalance
9 | * @typedef {import("@hashgraph/proto").proto.ITokenID} HieroProto.proto.ITokenID
10 | */
11 |
12 | /**
13 | * @augments {ObjectMap}
14 | */
15 | export default class NullableTokenDecimalMap extends ObjectMap {
16 | constructor() {
17 | super((s) => TokenId.fromString(s));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/account/TokenBalanceMap.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import TokenId from "../token/TokenId.js";
4 | import ObjectMap from "../ObjectMap.js";
5 |
6 | /**
7 | * @namespace proto
8 | * @typedef {import("@hashgraph/proto").proto.ITokenBalance} HieroProto.proto.ITokenBalance
9 | * @typedef {import("@hashgraph/proto").proto.ITokenID} HieroProto.proto.ITokenID
10 | */
11 |
12 | /**
13 | * @typedef {import("long")} Long
14 | */
15 |
16 | /**
17 | * @augments {ObjectMap}
18 | */
19 | export default class TokenBalanceMap extends ObjectMap {
20 | constructor() {
21 | super((s) => TokenId.fromString(s));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/account/TokenDecimalMap.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import TokenId from "../token/TokenId.js";
4 | import ObjectMap from "../ObjectMap.js";
5 |
6 | /**
7 | * @namespace proto
8 | * @typedef {import("@hashgraph/proto").proto.ITokenBalance} HieroProto.proto.ITokenBalance
9 | * @typedef {import("@hashgraph/proto").proto.ITokenID} HieroProto.proto.ITokenID
10 | */
11 |
12 | /**
13 | * @augments {ObjectMap}
14 | */
15 | export default class TokenDecimalMap extends ObjectMap {
16 | constructor() {
17 | super((s) => TokenId.fromString(s));
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/account/TokenTransferAccountMap.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import AccountId from "../account/AccountId.js";
4 | import ObjectMap from "../ObjectMap.js";
5 |
6 | /**
7 | * @augments {ObjectMap}
8 | */
9 | export default class TokenTransferAccountMap extends ObjectMap {
10 | constructor() {
11 | super((s) => AccountId.fromString(s));
12 | }
13 |
14 | toJSON() {
15 | const obj = {};
16 |
17 | this._map.forEach((value, key) => {
18 | // @ts-ignore
19 | obj[key] = value.toString();
20 | });
21 |
22 | return obj;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/address_book/IPv4AddressPart.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | export default class IPv4AddressPart {
4 | /**
5 | * @param {object} props
6 | * @param {number} [props.left]
7 | * @param {number} [props.right]
8 | */
9 | constructor(props = {}) {
10 | /**
11 | * @type {number | null}
12 | */
13 | this._left = null;
14 |
15 | if (props.left != null) {
16 | this.setLeft(props.left);
17 | }
18 |
19 | /**
20 | * @type {number | null}
21 | */
22 | this._right = null;
23 |
24 | if (props.right != null) {
25 | this.setRight(props.right);
26 | }
27 | }
28 |
29 | /**
30 | * @returns {?number}
31 | */
32 | get left() {
33 | return this._left;
34 | }
35 |
36 | /**
37 | * @param {number} part
38 | * @returns {this}
39 | */
40 | setLeft(part) {
41 | this._left = part;
42 | return this;
43 | }
44 |
45 | /**
46 | * @returns {?number}
47 | */
48 | get right() {
49 | return this._right;
50 | }
51 |
52 | /**
53 | * @param {number} part
54 | * @returns {this}
55 | */
56 | setRight(part) {
57 | this._right = part;
58 | return this;
59 | }
60 |
61 | /**
62 | * @returns {string}
63 | */
64 | toString() {
65 | if (this._left != null && this._right != null) {
66 | return `${this._left.toString()}.${this._right.toString()}`;
67 | } else {
68 | return "";
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/array.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * A simple efficient function for comparing byte arrays
5 | *
6 | * @param {Uint8Array} array1
7 | * @param {Uint8Array} array2
8 | * @returns {boolean}
9 | */
10 | export function arrayEqual(array1, array2) {
11 | if (array1 === array2) {
12 | return true;
13 | }
14 |
15 | if (array1.byteLength !== array2.byteLength) {
16 | return false;
17 | }
18 |
19 | const view1 = new DataView(
20 | array1.buffer,
21 | array1.byteOffset,
22 | array1.byteLength,
23 | );
24 | const view2 = new DataView(
25 | array2.buffer,
26 | array2.byteOffset,
27 | array2.byteLength,
28 | );
29 |
30 | let i = array1.byteLength;
31 |
32 | while (i--) {
33 | if (view1.getUint8(i) !== view2.getUint8(i)) {
34 | return false;
35 | }
36 | }
37 |
38 | return true;
39 | }
40 |
41 | /**
42 | * @param {Uint8Array} array
43 | * @param {Uint8Array} arrayPrefix
44 | * @returns {boolean}
45 | */
46 | export function arrayStartsWith(array, arrayPrefix) {
47 | if (array.byteLength < arrayPrefix.byteLength) {
48 | return false;
49 | }
50 |
51 | let i = arrayPrefix.byteLength;
52 |
53 | while (i--) {
54 | if (array[i] !== arrayPrefix[i]) {
55 | return false;
56 | }
57 | }
58 |
59 | return true;
60 | }
61 |
--------------------------------------------------------------------------------
/src/base32.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | // HIP-32: https://hips.hedera.com/hip/hip-32
4 | import { base32 } from "rfc4648";
5 |
6 | const decodeOpts = { loose: true };
7 | const encodeOpts = { pad: false };
8 |
9 | /**
10 | * Decodes the rfc4648 base32 string into a {@link Uint8Array}. If the input string is null, returns null.
11 | * @param {string} str the base32 string.
12 | * @returns {Uint8Array | ''}
13 | */
14 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
15 | const decode = (str) => str && base32.parse(str, decodeOpts);
16 |
17 | /**
18 | * Encodes the byte array into a rfc4648 base32 string without padding. If the input is null, returns null. Note with
19 | * the rfc4648 loose = true option, it allows lower case letters, padding, and auto corrects 0 -> O, 1 -> L, 8 -> B
20 | * @param {Buffer|Uint8Array} data
21 | * @returns {string}
22 | */
23 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
24 | const encode = (data) => data && base32.stringify(data, encodeOpts);
25 |
26 | export default {
27 | decode,
28 | encode,
29 | };
30 |
--------------------------------------------------------------------------------
/src/browser.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * The entry point for Browser applications
5 | */
6 |
7 | export * from "./exports.js";
8 |
9 | export { default as Client } from "./client/WebClient.js";
10 |
--------------------------------------------------------------------------------
/src/channel/MirrorChannel.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * @typedef {object} MirrorError
5 | * @property {number} code
6 | * @property {string} details
7 | */
8 |
9 | /**
10 | * @internal
11 | * @abstract
12 | */
13 | export default class MirrorChannel {
14 | /**
15 | * @abstract
16 | * @returns {void}
17 | */
18 | close() {
19 | throw new Error("not implemented");
20 | }
21 |
22 | /**
23 | * @abstract
24 | * @internal
25 | * @param {string} serviceName
26 | * @param {string} methodName
27 | * @param {Uint8Array} requestData
28 | * @param {(data: Uint8Array) => void} callback
29 | * @param {(error: MirrorError | Error) => void} error
30 | * @param {() => void} end
31 | * @returns {() => void}
32 | */
33 | makeServerStreamRequest(
34 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
35 | serviceName,
36 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
37 | methodName,
38 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
39 | requestData,
40 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
41 | callback,
42 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
43 | error,
44 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
45 | end,
46 | ) {
47 | throw new Error("not implemented");
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/cryptography/sha384.browser.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * @param {Uint8Array} data
5 | * @returns {Promise}
6 | */
7 | export async function digest(data) {
8 | // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest
9 | // This will be executed in a browser environment so the crypto object should be available if its
10 | // in secure context.
11 | // eslint-disable-next-line n/no-unsupported-features/node-builtins
12 | return new Uint8Array(await window.crypto.subtle.digest("SHA-384", data));
13 | }
14 |
--------------------------------------------------------------------------------
/src/cryptography/sha384.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import crypto from "crypto";
4 |
5 | /**
6 | * @param {Uint8Array} data
7 | * @returns {Promise}
8 | */
9 | export function digest(data) {
10 | // fallback to trying node-crypto which could be polyfilled by the browser environment
11 | return Promise.resolve(crypto.createHash("sha384").update(data).digest());
12 | }
13 |
14 | /**
15 | * @param {Uint8Array} data
16 | * @returns {Uint8Array}
17 | */
18 | export function digestSync(data) {
19 | return crypto.createHash("sha384").update(data).digest();
20 | }
21 |
--------------------------------------------------------------------------------
/src/cryptography/sha384.native.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import CryptoJS from "crypto-js";
4 | import * as hex from "../encoding/hex.js";
5 |
6 | /**
7 | * @param {Uint8Array} data
8 | * @returns {Promise}
9 | */
10 | // eslint-disable-next-line @typescript-eslint/require-await
11 | export async function digest(data) {
12 | return Promise.resolve(
13 | hex.decode(
14 | CryptoJS.SHA384(CryptoJS.enc.Hex.parse(hex.encode(data))).toString(
15 | CryptoJS.enc.Hex,
16 | ),
17 | ),
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/src/encoding/base64.native.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import { atob, btoa } from "js-base64";
4 |
5 | /**
6 | * @param {string} text
7 | * @returns {Uint8Array}
8 | */
9 | export function decode(text) {
10 | return Uint8Array.from(atob(text), (c) => c.charCodeAt(0));
11 | }
12 |
13 | /**
14 | * @param {Uint8Array} data
15 | * @returns {string};
16 | */
17 | export function encode(data) {
18 | return btoa(String.fromCharCode.apply(null, Array.from(data)));
19 | }
20 |
--------------------------------------------------------------------------------
/src/encoding/hex.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * @param {Uint8Array} data
5 | * @returns {string}
6 | */
7 | export function encode(data) {
8 | return Buffer.from(data).toString("hex");
9 | }
10 |
11 | /**
12 | * @param {string} text
13 | * @returns {Uint8Array}
14 | */
15 | export function decode(text) {
16 | const str = text.startsWith("0x") ? text.substring(2) : text;
17 | return Buffer.from(str, "hex");
18 | }
19 |
20 | /**
21 | * Encode with a specified length. Supports zero padding if the most significant byte is 0
22 | *
23 | * https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L315
24 | *
25 | * @param {Uint8Array} value
26 | * @param {number} length
27 | * @returns {string}
28 | */
29 | export function hexZeroPadded(value, length) {
30 | const HexCharacters = "0123456789abcdef";
31 |
32 | // https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L243
33 | let result = "0x";
34 | for (let i = 0; i < value.length; i++) {
35 | let v = value[i];
36 | result += HexCharacters[(v & 0xf0) >> 4] + HexCharacters[v & 0x0f];
37 | }
38 |
39 | // https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L315
40 | if (result.length > 2 * length + 2) {
41 | console.log("result out of range", "result");
42 | }
43 |
44 | while (result.length < 2 * length + 2) {
45 | result = "0x0" + result.substring(2);
46 | }
47 |
48 | return result.substring(2);
49 | }
50 |
--------------------------------------------------------------------------------
/src/encoding/utf8.browser.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * @param {Uint8Array} data
5 | * @returns {string}
6 | */
7 | export function decode(data) {
8 | // eslint-disable-next-line n/no-unsupported-features/node-builtins
9 | return new TextDecoder().decode(data);
10 | }
11 |
12 | /**
13 | * @param {string} text
14 | * @returns {Uint8Array}
15 | */
16 | export function encode(text) {
17 | // eslint-disable-next-line n/no-unsupported-features/node-builtins
18 | return new TextEncoder().encode(text);
19 | }
20 |
--------------------------------------------------------------------------------
/src/encoding/utf8.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * @param {Uint8Array} data
5 | * @returns {string}
6 | */
7 | export function decode(data) {
8 | return Buffer.from(data).toString("utf8");
9 | }
10 |
11 | /**
12 | * @param {string} text
13 | * @returns {Uint8Array}
14 | */
15 | export function encode(text) {
16 | return Buffer.from(text, "utf8");
17 | }
18 |
--------------------------------------------------------------------------------
/src/encoding/utf8.native.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import utf8 from "utf8";
4 | import * as hex from "./hex.native.js";
5 |
6 | /**
7 | * @param {Uint8Array} data
8 | * @returns {string}
9 | */
10 | export function decode(data) {
11 | return utf8.decode(hex.encodeToByteString(data));
12 | }
13 |
14 | /**
15 | * @param {string} text
16 | * @returns {Uint8Array}
17 | */
18 | export function encode(text) {
19 | return hex.decodeFromByteString(utf8.encode(text));
20 | }
21 |
--------------------------------------------------------------------------------
/src/http/HttpError.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
3 | import HttpStatus from "./HttpStatus.js";
4 |
5 | /**
6 | * Describes how the http request failed.
7 | */
8 | export default class HttpError extends Error {
9 | /**
10 | * @param {HttpStatus} status
11 | */
12 | constructor(status) {
13 | super(`failed with error code: ${status.toString()}`);
14 |
15 | /**
16 | * @readonly
17 | */
18 | this.status = status;
19 |
20 | this.name = "HttpError";
21 |
22 | if (typeof Error.captureStackTrace !== "undefined") {
23 | Error.captureStackTrace(this, HttpError);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/http/HttpStatus.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | export default class HttpStatus {
4 | /**
5 | * @hideconstructor
6 | * @internal
7 | * @param {number} code
8 | */
9 | constructor(code) {
10 | /** @readonly */
11 | this._code = code;
12 |
13 | Object.freeze(this);
14 | }
15 |
16 | /**
17 | * @internal
18 | * @param {number} code
19 | * @returns {HttpStatus}
20 | */
21 | static _fromValue(code) {
22 | return new HttpStatus(code);
23 | }
24 |
25 | /**
26 | * @returns {string}
27 | */
28 | toString() {
29 | return this._code.toString();
30 | }
31 |
32 | /**
33 | * @returns {number}
34 | */
35 | valueOf() {
36 | return this._code;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * The entry point for NodeJS applications
5 | */
6 |
7 | export * from "./exports.js";
8 |
9 | export { default as LocalProvider } from "./LocalProvider.js";
10 | export { default as Client } from "./client/NodeClient.js";
11 |
--------------------------------------------------------------------------------
/src/long.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import BigNumber from "bignumber.js";
4 |
5 | /**
6 | * @typedef {{low: number, high: number, unsigned: boolean}} LongObject
7 | * @typedef {import("long")} Long
8 | */
9 |
10 | /**
11 | * @param {Long | number | string | LongObject | BigNumber} value
12 | * @returns {BigNumber}
13 | */
14 | export function valueToLong(value) {
15 | if (BigNumber.isBigNumber(value)) {
16 | return value;
17 | } else {
18 | return new BigNumber(value.toString());
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/native.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * The entry point for React Native applications
5 | */
6 |
7 | export * from "./exports.js";
8 |
9 | export { default as Client } from "./client/NativeClient.js";
10 |
--------------------------------------------------------------------------------
/src/query/MirrorNodeContractEstimateQuery.js:
--------------------------------------------------------------------------------
1 | import MirrorNodeContractQuery from "./MirrorNodeContractQuery.js";
2 |
3 | /**
4 | * @typedef {import("../channel/Channel.js").default} Channel
5 | * @typedef {import("../client/Client.js").default<*, *>} Client
6 | */
7 |
8 | /**
9 | * A query that estimates the gas required for a contract function call using the Hedera Mirror Node.
10 | *
11 | * This query simulates a contract call to estimate the amount of gas that would be required
12 | * to execute the same call on the main network. It's useful for determining the appropriate
13 | * gas limit before submitting an actual transaction.
14 | */
15 | export default class MirrorNodeContractCallQuery extends MirrorNodeContractQuery {
16 | /**
17 | * @returns {object}
18 | */
19 | get JSONPayload() {
20 | if (this.callData == null) {
21 | throw new Error("Call data is required.");
22 | }
23 |
24 | return {
25 | data: Buffer.from(this.callData).toString("hex"),
26 | from: this.senderEvmAddress,
27 | to: this.contractEvmAddress,
28 | estimate: true,
29 | gasPrice: this.gasPrice?.toString(),
30 | gas: this.gasLimit?.toString(),
31 | blockNumber: this.blockNumber?.toString(),
32 | value: this.value?.toString(),
33 | };
34 | }
35 |
36 | /**
37 | * @param {Client} client
38 | * @returns {Promise}
39 | */
40 | async execute(client) {
41 | const mirrorNodeRequest = await this.performMirrorNodeRequest(
42 | client,
43 | this.JSONPayload,
44 | );
45 |
46 | return Number(mirrorNodeRequest.result);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/token/AirdropPendingTransaction.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 | import Transaction from "../transaction/Transaction.js";
3 |
4 | /**
5 | * @typedef {import("../token/PendingAirdropId.js").default} PendingAirdropId
6 | */
7 | export default class AirdropPendingTransaction extends Transaction {
8 | /**
9 | * @param {object} [props]
10 | * @param {PendingAirdropId[]} [props.pendingAirdropIds]
11 | */
12 | constructor(props) {
13 | /**
14 | * @private
15 | * @type {PendingAirdropId[]}
16 | */
17 | super();
18 |
19 | /**
20 | * @private
21 | * @type {PendingAirdropId[]}
22 | */
23 | this._pendingAirdropIds = [];
24 |
25 | if (props?.pendingAirdropIds != null) {
26 | this._pendingAirdropIds = props.pendingAirdropIds;
27 | }
28 | }
29 |
30 | /**
31 | * @returns {PendingAirdropId[]}
32 | */
33 | get pendingAirdropIds() {
34 | return this._pendingAirdropIds;
35 | }
36 |
37 | /**
38 | *
39 | * @param {PendingAirdropId} pendingAirdropId
40 | * @returns {this}
41 | */
42 | addPendingAirdropId(pendingAirdropId) {
43 | this._requireNotFrozen();
44 | this._pendingAirdropIds.push(pendingAirdropId);
45 | return this;
46 | }
47 |
48 | /**
49 | *
50 | * @param {PendingAirdropId[]} pendingAirdropIds
51 | * @returns {this}
52 | */
53 | setPendingAirdropIds(pendingAirdropIds) {
54 | this._requireNotFrozen();
55 | this._pendingAirdropIds = pendingAirdropIds;
56 | return this;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/token/FeeAssessmentMethod.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | export default class FeeAssessmentMethod {
4 | /**
5 | * @hideconstructor
6 | * @internal
7 | * @param {boolean} value
8 | */
9 | constructor(value) {
10 | /** @readonly */
11 | this._value = value;
12 |
13 | Object.freeze(this);
14 | }
15 |
16 | /**
17 | * @returns {string}
18 | */
19 | toString() {
20 | switch (this) {
21 | case FeeAssessmentMethod.Inclusive:
22 | return "INCLUSIVE";
23 | case FeeAssessmentMethod.Exclusive:
24 | return "EXCLUSIVE";
25 | default:
26 | return `UNKNOWN (${this._value.toString()})`;
27 | }
28 | }
29 |
30 | /**
31 | * @internal
32 | * @param {boolean} value
33 | * @returns {FeeAssessmentMethod}
34 | */
35 | static _fromValue(value) {
36 | switch (value) {
37 | case false:
38 | return FeeAssessmentMethod.Inclusive;
39 | case true:
40 | return FeeAssessmentMethod.Exclusive;
41 | }
42 | }
43 |
44 | /**
45 | * @returns {boolean}
46 | */
47 | valueOf() {
48 | return this._value;
49 | }
50 | }
51 |
52 | FeeAssessmentMethod.Inclusive = new FeeAssessmentMethod(false);
53 | FeeAssessmentMethod.Exclusive = new FeeAssessmentMethod(true);
54 |
--------------------------------------------------------------------------------
/src/token/PendingAirdropRecord.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 | /**
3 | * @namespace proto
4 | * @typedef {import("@hashgraph/proto").proto.PendingAirdropRecord} HieroProto.proto.PendingAirdropRecord
5 | */
6 |
7 | import Long from "long";
8 | import PendingAirdropId from "./PendingAirdropId.js";
9 |
10 | export default class PendingAirdropRecord {
11 | /**
12 | * @param {object} props
13 | * @param {PendingAirdropId} props.airdropId
14 | * @param {Long} props.amount
15 | */
16 | constructor(props) {
17 | this.airdropId = props.airdropId;
18 | this.amount = props.amount;
19 | }
20 |
21 | /**
22 | * @returns {HieroProto.proto.PendingAirdropRecord}
23 | */
24 | toBytes() {
25 | return {
26 | pendingAirdropId: this.airdropId.toBytes(),
27 | pendingAirdropValue: {
28 | amount: this.amount,
29 | },
30 | };
31 | }
32 |
33 | /**
34 | * @param {HieroProto.proto.PendingAirdropRecord} pb
35 | * @returns {PendingAirdropRecord}
36 | */
37 | static fromBytes(pb) {
38 | if (pb.pendingAirdropId == null) {
39 | throw new Error("pendingAirdropId is required");
40 | }
41 |
42 | const airdropId = PendingAirdropId.fromBytes(pb.pendingAirdropId);
43 | const amount = pb.pendingAirdropValue?.amount;
44 |
45 | return new PendingAirdropRecord({
46 | airdropId: airdropId,
47 | amount: amount ? amount : Long.ZERO,
48 | });
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/token/TokenReference.js:
--------------------------------------------------------------------------------
1 | import NftId from "./NftId.js";
2 | import TokenId from "./TokenId.js";
3 |
4 | /**
5 | * @namespace proto
6 | * @typedef {import("@hashgraph/proto").proto.TokenReference} HieroProto.proto.TokenReference
7 | */
8 |
9 | export default class TokenReference {
10 | constructor() {
11 | /**
12 | * @public
13 | * @type {?TokenId}
14 | */
15 | this.fungibleToken = null;
16 | /**
17 | * @public
18 | * @type {?NftId}
19 | */
20 | this.nft = null;
21 | }
22 |
23 | /**
24 | * @public
25 | * @param {HieroProto.proto.TokenReference} reference
26 | * @returns {TokenReference}
27 | */
28 | static _fromProtobuf(reference) {
29 | return {
30 | fungibleToken:
31 | reference.fungibleToken != undefined
32 | ? TokenId._fromProtobuf(reference.fungibleToken)
33 | : null,
34 | nft:
35 | reference.nft != undefined
36 | ? NftId._fromProtobuf(reference.nft)
37 | : null,
38 | };
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/topic/SubscriptionHandle.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | /**
4 | * Represents a handle for managing subscriptions to topics in the Hedera network.
5 | *
6 | * The `SubscriptionHandle` class provides methods to manage the lifecycle of a subscription,
7 | * including setting a callback function to be executed when an event occurs and unsubscribing
8 | * from the topic notifications. It is primarily used for handling real-time updates from the
9 | * Hedera network like topic subscriptions.
10 | */
11 | export default class SubscriptionHandle {
12 | constructor() {
13 | /** @type {{(): void} | null} */
14 | this._call = null;
15 |
16 | /** @type {boolean} */
17 | this._unsubscribed = false;
18 | }
19 |
20 | /**
21 | * @param {() => void} call
22 | * @returns {void}
23 | */
24 | _setCall(call) {
25 | this._call = call;
26 | }
27 |
28 | unsubscribe() {
29 | if (this._call != null) {
30 | this._unsubscribed = true;
31 | this._call();
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/transaction/NodeAccountIdSignatureMapLegacy.js:
--------------------------------------------------------------------------------
1 | import ObjectMap from "../ObjectMap.js";
2 | import PublicKey from "../PublicKey.js";
3 |
4 | /**
5 | * @deprecated
6 | * @augments {ObjectMap}
7 | */
8 | export default class NodeAccountIdSignatureMap extends ObjectMap {
9 | constructor() {
10 | super((s) => PublicKey.fromString(s));
11 | }
12 |
13 | /**
14 | * @param {import("@hashgraph/proto").proto.ISignatureMap} sigMap
15 | * @returns {NodeAccountIdSignatureMap}
16 | */
17 | static _fromTransactionSigMap(sigMap) {
18 | // eslint-disable-next-line deprecation/deprecation
19 | const signatures = new NodeAccountIdSignatureMap();
20 | const sigPairs = sigMap.sigPair != null ? sigMap.sigPair : [];
21 |
22 | for (const sigPair of sigPairs) {
23 | if (sigPair.pubKeyPrefix != null) {
24 | if (sigPair.ed25519 != null) {
25 | signatures._set(
26 | PublicKey.fromBytesED25519(sigPair.pubKeyPrefix),
27 | sigPair.ed25519,
28 | );
29 | } else if (sigPair.ECDSASecp256k1 != null) {
30 | signatures._set(
31 | PublicKey.fromBytesECDSA(sigPair.pubKeyPrefix),
32 |
33 | sigPair.ECDSASecp256k1,
34 | );
35 | }
36 | }
37 | }
38 |
39 | return signatures;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/transaction/SignatureMapLegacy.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable deprecation/deprecation */
2 | import NodeAccountIdSignatureMapLegacy from "./NodeAccountIdSignatureMapLegacy.js";
3 | import ObjectMap from "../ObjectMap.js";
4 | import AccountId from "../account/AccountId.js";
5 |
6 | /**
7 | * @deprecated
8 | * @augments {ObjectMap}
9 | */
10 | export default class SignatureMap extends ObjectMap {
11 | constructor() {
12 | super((s) => AccountId.fromString(s));
13 | }
14 |
15 | /**
16 | * @param {import("./Transaction.js").default} transaction
17 | * @returns {SignatureMap}
18 | */
19 | static _fromTransaction(transaction) {
20 | const signatures = new SignatureMap();
21 |
22 | for (let i = 0; i < transaction._nodeAccountIds.length; i++) {
23 | const sigMap = transaction._signedTransactions.get(i).sigMap;
24 |
25 | if (sigMap != null) {
26 | signatures._set(
27 | transaction._nodeAccountIds.list[i],
28 | NodeAccountIdSignatureMapLegacy._fromTransactionSigMap(
29 | sigMap,
30 | ),
31 | );
32 | }
33 | }
34 |
35 | return signatures;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/transaction/SignaturePairMap.js:
--------------------------------------------------------------------------------
1 | import ObjectMap from "../ObjectMap.js";
2 | import PublicKey from "../PublicKey.js";
3 |
4 | /**
5 | * @augments {ObjectMap}
6 | */
7 | export default class SignaturePairMap extends ObjectMap {
8 | constructor() {
9 | super((s) => PublicKey.fromString(s));
10 | }
11 |
12 | /**
13 | * This function is used to create a SignaturePairMap from an already built transaction.
14 | * @param {import("@hashgraph/proto").proto.ISignatureMap} sigMap
15 | * @returns {SignaturePairMap}
16 | */
17 | static _fromTransactionSigMap(sigMap) {
18 | const signatures = new SignaturePairMap();
19 |
20 | const sigPairs = sigMap.sigPair != null ? sigMap.sigPair : [];
21 |
22 | for (const sigPair of sigPairs) {
23 | if (sigPair.pubKeyPrefix == null) {
24 | continue;
25 | }
26 |
27 | if (sigPair.ed25519 != null) {
28 | signatures._set(
29 | PublicKey.fromBytesED25519(sigPair.pubKeyPrefix),
30 | sigPair.ed25519,
31 | );
32 | } else if (sigPair.ECDSASecp256k1 != null) {
33 | signatures._set(
34 | PublicKey.fromBytesECDSA(sigPair.pubKeyPrefix),
35 | sigPair.ECDSASecp256k1,
36 | );
37 | }
38 | }
39 |
40 | return signatures;
41 | }
42 |
43 | /**
44 | *
45 | * @param {PublicKey} pubKey
46 | * @param {Uint8Array} signature
47 | * @returns {SignaturePairMap}
48 | */
49 | addSignature(pubKey, signature) {
50 | this._set(pubKey, signature);
51 | return this;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/transaction/TokenTransfer.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
--------------------------------------------------------------------------------
/src/transaction/TransactionHashMap.js:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: Apache-2.0
2 |
3 | import AccountId from "../account/AccountId.js";
4 | import * as sha384 from "../cryptography/sha384.js";
5 | import ObjectMap from "../ObjectMap.js";
6 |
7 | /**
8 | * @namespace proto
9 | * @typedef {import("@hashgraph/proto").proto.ITransaction} HieroProto.proto.ITransaction
10 | */
11 |
12 | /**
13 | * @augments {ObjectMap}
14 | */
15 | export default class TransactionHashMap extends ObjectMap {
16 | constructor() {
17 | super((s) => AccountId.fromString(s));
18 | }
19 |
20 | /**
21 | * @param {import("./Transaction.js").default} transaction
22 | * @returns {Promise}
23 | */
24 | static async _fromTransaction(transaction) {
25 | const hashes = new TransactionHashMap();
26 |
27 | for (let i = 0; i < transaction._nodeAccountIds.length; i++) {
28 | const nodeAccountId = transaction._nodeAccountIds.list[i];
29 | const tx = /** @type {HieroProto.proto.ITransaction} */ (
30 | transaction._transactions.get(i)
31 | );
32 | const hash = await sha384.digest(
33 | /** @type {Uint8Array} */ (tx.signedTransactionBytes),
34 | );
35 |
36 | hashes._set(nodeAccountId, hash);
37 | }
38 |
39 | return hashes;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/types.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Global type declarations for the Hedera SDK
3 | */
4 |
5 | declare const __SDK_VERSION__: string | undefined;
6 |
--------------------------------------------------------------------------------
/src/version.js:
--------------------------------------------------------------------------------
1 | export const SDK_VERSION =
2 | typeof __SDK_VERSION__ !== "undefined" ? __SDK_VERSION__ : "DEV";
3 |
--------------------------------------------------------------------------------
/tck/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/tck/Dockerfile:
--------------------------------------------------------------------------------
1 | # Stage 1: Build
2 | FROM node:20-alpine AS build
3 |
4 | WORKDIR /app
5 |
6 | # Copy package files
7 | COPY package.json pnpm-lock.yaml* ./
8 |
9 | # Install pnpm
10 | RUN npm install -g pnpm
11 |
12 | # Override the local SDK dependency with the npm version and add missing dependencies
13 | RUN pnpm add @hashgraph/sdk@^2.63.0-beta.1 long@^5.2.3 @hashgraph/proto@^2.17.0-beta.1
14 |
15 | # Install dependencies
16 | RUN pnpm install
17 |
18 | # Copy TCK source code
19 | COPY . .
20 |
21 | # Stage 2: Runtime
22 | FROM node:20-alpine
23 |
24 | WORKDIR /app
25 |
26 | # Install pnpm in the runtime stage
27 | RUN npm install -g pnpm
28 |
29 | # Copy only the necessary files from the build stage
30 | COPY --from=build /app .
31 |
32 | # Expose the port used by the server
33 | EXPOSE 8544
34 |
35 | # Start the server
36 | CMD ["pnpm", "start"]
--------------------------------------------------------------------------------
/tck/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | tck-server:
3 | image: tck-js-server
4 | networks:
5 | - hedera-network-node
6 | - hedera-mirror-node
7 | environment:
8 | NETWORK: "${NETWORK:-local}"
9 | build:
10 | context: .
11 | ports:
12 | - "8544:8544"
13 | hiero-tck-client:
14 | image: ivaylogarnev/hiero-tck-client
15 | networks:
16 | - hedera-network-node
17 | - hedera-mirror-node
18 | environment:
19 | TEST: "${TEST:-ALL}"
20 | NETWORK: "${NETWORK:-local}"
21 | OPERATOR_ACCOUNT_ID: "${OPERATOR_ACCOUNT_ID:-0.0.1022}"
22 | OPERATOR_ACCOUNT_PRIVATE_KEY: "${OPERATOR_ACCOUNT_PRIVATE_KEY:-302e020100300506032b657004220420a608e2130a0a3cb34f86e757303c862bee353d9ab77ba4387ec084f881d420d4}"
23 | JSON_RPC_SERVER_URL: "http://tck-server:8544"
24 | NODE_IP: "network-node:50211"
25 | MIRROR_NODE_REST_URL: "${MIRROR_NODE_REST_URL:-http://mirror-node-rest:5551}"
26 | MIRROR_NODE_REST_JAVA_URL: "${MIRROR_NODE_REST_JAVA_URL:-http://mirror-node-rest-java:8084}"
27 | depends_on:
28 | - tck-server
29 |
30 | networks:
31 | hedera-network-node:
32 | external: true
33 | hedera-mirror-node:
34 | external: true
35 |
--------------------------------------------------------------------------------
/tck/mapping.ts:
--------------------------------------------------------------------------------
1 | import { sdk } from "./sdk_data";
2 | import { RpcMethodParams } from "./params/sdk";
3 |
4 | /**
5 | * Very primitive catch-all mapping prototype
6 | * @returns {Promise<*>}
7 | * @param {Input} input
8 | */
9 | export default async function mapMethods({
10 | callClass,
11 | methods,
12 | }: RpcMethodParams): Promise {
13 | const cl: any = (await import("@hashgraph/sdk"))[callClass];
14 |
15 | let currentObject: any = new cl();
16 | for (let { name, param } of methods) {
17 | if (param === "client") {
18 | param = sdk.getClient();
19 | }
20 |
21 | if (typeof currentObject[name] === "function") {
22 | currentObject = await currentObject[name](param);
23 | } else if (typeof cl[name] === "function") {
24 | currentObject = await cl[name](param);
25 | } else if (typeof currentObject[name] === "object") {
26 | currentObject = await currentObject[name];
27 | } else {
28 | throw Error(`${callClass}.${name}() isn't a function`);
29 | }
30 | }
31 | return currentObject;
32 | }
33 |
--------------------------------------------------------------------------------
/tck/methods/index.ts:
--------------------------------------------------------------------------------
1 | import glob from "glob";
2 | import path from "path";
3 |
4 | // Require all files in this folder in one module.export
5 |
6 | let allMethods: Record = {};
7 | glob.sync(path.join(__dirname, "**/*.ts")).forEach((file) => {
8 | allMethods = { ...allMethods, ...require(path.resolve(file)) };
9 | });
10 |
11 | export default allMethods;
12 |
--------------------------------------------------------------------------------
/tck/methods/sdk.ts:
--------------------------------------------------------------------------------
1 | import { Client, AccountId } from "@hashgraph/sdk";
2 |
3 | import { sdk } from "../sdk_data";
4 | import { SdkResponse } from "../response/sdk";
5 | import { SdkSetupParams } from "../params/sdk";
6 |
7 | export default {
8 | setup: ({
9 | operatorAccountId,
10 | operatorPrivateKey,
11 | nodeIp,
12 | nodeAccountId,
13 | mirrorNetworkIp,
14 | }: SdkSetupParams): SdkResponse => {
15 | let client: Client;
16 |
17 | if (nodeIp && nodeAccountId && mirrorNetworkIp) {
18 | const node = { [nodeIp]: AccountId.fromString(nodeAccountId) };
19 | client = Client.forNetwork(node);
20 | } else {
21 | client = Client.forTestnet();
22 | }
23 |
24 | client.setOperator(operatorAccountId, operatorPrivateKey);
25 | client.setRequestTimeout(30000);
26 |
27 | sdk.client = client;
28 |
29 | return {
30 | message: `Successfully setup ${client} client.`,
31 | status: "SUCCESS",
32 | };
33 | },
34 | reset: (): SdkResponse => {
35 | sdk.client = null;
36 | return { status: "SUCCESS" };
37 | },
38 | };
39 |
--------------------------------------------------------------------------------
/tck/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tck",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "server.ts",
6 | "scripts": {
7 | "start": "nodemon server.ts",
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "start:debug": "nodemon --inspect=9229 --exec node --inspect --require ts-node/register server.ts"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "@hashgraph/sdk": "file:..",
15 | "body-parser": "^1.20.2",
16 | "express": "^4.19.2",
17 | "glob": "^8.0.3",
18 | "json-rpc-2.0": "^1.7.0",
19 | "lossless-json": "^1.0.5"
20 | },
21 | "devDependencies": {
22 | "@types/body-parser": "^1.19.5",
23 | "@types/express": "^4.17.21",
24 | "@types/glob": "^8.1.0",
25 | "@types/lossless-json": "^1.0.4",
26 | "nodemon": "^3.1.10",
27 | "ts-node": "^10.9.2"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tck/params/allowance.ts:
--------------------------------------------------------------------------------
1 | export interface AllowanceParams {
2 | readonly ownerAccountId: string;
3 | readonly spenderAccountId: string;
4 | readonly hbar: HbarAllowanceParams;
5 | readonly token?: TokenAllowanceParams;
6 | readonly nft?: NftAllowanceParams;
7 | }
8 |
9 | export interface HbarAllowanceParams {
10 | readonly amount: string;
11 | }
12 |
13 | export interface TokenAllowanceParams {
14 | readonly tokenId: string;
15 | readonly amount: string;
16 | }
17 |
18 | export interface NftAllowanceParams {
19 | readonly tokenId: string;
20 | readonly serialNumbers?: string[];
21 | readonly approvedForAll?: boolean;
22 | readonly delegateSpenderAccountId?: string;
23 | }
24 |
--------------------------------------------------------------------------------
/tck/params/key.ts:
--------------------------------------------------------------------------------
1 | export interface KeyGenerationParams {
2 | readonly type: string;
3 | readonly fromKey?: string;
4 | readonly threshold?: number;
5 | readonly keys?: KeyGenerationParams[];
6 | }
7 |
--------------------------------------------------------------------------------
/tck/params/sdk.ts:
--------------------------------------------------------------------------------
1 | export interface SdkSetupParams {
2 | readonly operatorAccountId: string;
3 | readonly operatorPrivateKey: string;
4 | readonly nodeIp?: string;
5 | readonly nodeAccountId?: string;
6 | readonly mirrorNetworkIp?: string;
7 | }
8 |
9 | type RpcMethod = {
10 | readonly name: string;
11 | readonly param: any;
12 | };
13 |
14 | export interface RpcMethodParams {
15 | readonly callClass: string;
16 | readonly methods: RpcMethod[];
17 | }
18 |
--------------------------------------------------------------------------------
/tck/params/transfer.ts:
--------------------------------------------------------------------------------
1 | export interface TransferCryptoParams {
2 | readonly transfers?: TransferParams[];
3 | readonly commonTransactionParams?: Record;
4 | }
5 |
6 | export interface TransferParams {
7 | readonly hbar?: HbarTransferParams;
8 | readonly token?: TokenTransferParams;
9 | readonly nft?: NftTransferParams;
10 | readonly approved?: boolean;
11 | }
12 |
13 | export interface HbarTransferParams {
14 | readonly accountId: string;
15 | readonly evmAddress: string;
16 | readonly amount: string;
17 | }
18 |
19 | export interface NftTransferParams {
20 | readonly senderAccountId: string;
21 | readonly receiverAccountId: string;
22 | readonly tokenId: string;
23 | readonly serialNumber: string;
24 | }
25 |
26 | export interface TokenTransferParams {
27 | readonly accountId: string;
28 | readonly tokenId: string;
29 | readonly amount: string;
30 | readonly decimals: number;
31 | }
32 |
--------------------------------------------------------------------------------
/tck/response/account.ts:
--------------------------------------------------------------------------------
1 | export interface AccountResponse {
2 | readonly accountId?: string;
3 | readonly status: string;
4 | }
5 |
--------------------------------------------------------------------------------
/tck/response/asn1-decode.ts:
--------------------------------------------------------------------------------
1 | export interface Asn1DecodedKeyResponse {
2 | readonly keyTypes: string[];
3 | readonly isPublicKey: boolean;
4 | readonly isKeyListHex: boolean;
5 | }
6 |
--------------------------------------------------------------------------------
/tck/response/json-rpc-error.ts:
--------------------------------------------------------------------------------
1 | import { JSONRPCErrorCode } from "json-rpc-2.0";
2 |
3 | export const JSONRPCErrorCodeCustom = {
4 | ...JSONRPCErrorCode,
5 | HederaError: -32001,
6 | };
7 |
8 | export type JSONRPCErrorCodeCustom = typeof JSONRPCErrorCodeCustom;
9 |
--------------------------------------------------------------------------------
/tck/response/key.ts:
--------------------------------------------------------------------------------
1 | export interface KeyGenerationResponse {
2 | key: string;
3 | privateKeys: string[];
4 | }
5 |
--------------------------------------------------------------------------------
/tck/response/sdk.ts:
--------------------------------------------------------------------------------
1 | export interface SdkResponse {
2 | readonly status: string;
3 | readonly message?: string;
4 | }
5 |
--------------------------------------------------------------------------------
/tck/response/token.ts:
--------------------------------------------------------------------------------
1 | export interface TokenResponse {
2 | readonly tokenId?: string;
3 | readonly status: string;
4 | }
5 |
6 | export interface TokenMintResponse {
7 | readonly tokenId?: string;
8 | readonly newTotalSupply?: string;
9 | readonly serialNumbers?: string[];
10 | readonly status: string;
11 | }
12 |
13 | export interface TokenBurnResponse {
14 | readonly tokenId?: string;
15 | readonly newTotalSupply?: string;
16 | readonly status: string;
17 | }
18 |
--------------------------------------------------------------------------------
/tck/sdk_data.ts:
--------------------------------------------------------------------------------
1 | import { Client } from "@hashgraph/sdk";
2 |
3 | export const sdk = {
4 | client: null,
5 | getClient(): Client {
6 | if (this.client == null) {
7 | throw new Error("Client not set up");
8 | }
9 |
10 | return this.client;
11 | },
12 | };
13 |
--------------------------------------------------------------------------------
/tck/utils/constants/config.ts:
--------------------------------------------------------------------------------
1 | export const DEFAULT_GRPC_DEADLINE = 30000;
2 |
--------------------------------------------------------------------------------
/tck/utils/constants/properties.ts:
--------------------------------------------------------------------------------
1 | import { TokenType, TokenSupplyType } from "@hashgraph/sdk";
2 |
3 | export const tokenTypeMap = {
4 | ft: TokenType.FungibleCommon,
5 | nft: TokenType.NonFungibleUnique,
6 | };
7 |
8 | export const supplyTypeMap = {
9 | finite: TokenSupplyType.Finite,
10 | infinite: TokenSupplyType.Infinite,
11 | };
12 |
--------------------------------------------------------------------------------
/tck/utils/custom-error.ts:
--------------------------------------------------------------------------------
1 | export class CustomError extends Error {
2 | code: number;
3 |
4 | constructor(message: string, code: number) {
5 | super(message);
6 | this.code = code;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tck/utils/enums/account-key.ts:
--------------------------------------------------------------------------------
1 | export enum AccountKey {
2 | ED25519_PRIVATE_KEY = "ed25519PrivateKey",
3 | ECDSA_SECP256K1_PRIVATE_KEY = "ecdsaSecp256k1PrivateKey",
4 | ED25519_PUBLIC_KEY = "ed25519PublicKey",
5 | ECDSA_SECP256K1_PUBLIC_KEY = "ecdsaSecp256k1PublicKey",
6 | KEY_LIST = "keyList",
7 | THRESHOLD_KEY = "thresholdKey",
8 | EVM_ADDRESS = "evmAddress",
9 | }
10 |
--------------------------------------------------------------------------------
/tck/utils/invalid-param-error.ts:
--------------------------------------------------------------------------------
1 | import { JSONRPCErrorCode } from "json-rpc-2.0";
2 |
3 | import { CustomError } from "./custom-error";
4 |
5 | export const invalidParamError = (message: string): T => {
6 | throw new CustomError(
7 | `invalid parameters: ${message}`,
8 | JSONRPCErrorCode.InvalidParams,
9 | );
10 | };
11 |
--------------------------------------------------------------------------------
/test/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | plugins: ["vitest"],
4 | env: {
5 | browser: true,
6 | node: true,
7 | es6: true,
8 | },
9 | parser: "@babel/eslint-parser",
10 | extends: ["eslint:recommended", "plugin:vitest/recommended"],
11 | globals: {
12 | expect: "readonly",
13 | describe: "readonly",
14 | it: "readonly",
15 | beforeAll: "readonly",
16 | afterAll: "readonly",
17 | beforeEach: "readonly",
18 | afterEach: "readonly",
19 | },
20 | rules: {
21 | "vitest/valid-expect": "off",
22 | "vitest/expect-expect": "off",
23 | "vitest/valid-title": "off",
24 | "vitest/no-disabled-tests": "warn",
25 | },
26 | };
27 |
--------------------------------------------------------------------------------
/test/integration/AccountIdTest.js:
--------------------------------------------------------------------------------
1 | import { AccountId, TokenId } from "../../src/exports.js";
2 | import IntegrationTestEnv, { Client } from "./client/NodeIntegrationTestEnv.js";
3 |
4 | describe("AccountId", function () {
5 | let client;
6 |
7 | beforeAll(async function () {
8 | client = Client.forMainnet();
9 | });
10 |
11 | it("should generate checksum for account ID", function () {
12 | const accountId = new AccountId(123);
13 |
14 | expect(accountId.num.toNumber()).to.eql(123);
15 | expect(accountId.realm.toNumber()).to.eql(0);
16 | expect(accountId.shard.toNumber()).to.eql(0);
17 |
18 | expect(accountId.toStringWithChecksum(client)).to.be.eql(
19 | "0.0.123-vfmkw",
20 | );
21 | });
22 |
23 | it("should generate checksum for token ID", function () {
24 | const tokenId = new TokenId(123);
25 |
26 | expect(tokenId.num.toNumber()).to.eql(123);
27 | expect(tokenId.realm.toNumber()).to.eql(0);
28 | expect(tokenId.shard.toNumber()).to.eql(0);
29 |
30 | expect(tokenId.toStringWithChecksum(client)).to.be.eql("0.0.123-vfmkw");
31 | });
32 |
33 | it("should parse previewnet ID with checksum {0.0.123-ghaha}", function () {
34 | let err = false;
35 |
36 | try {
37 | AccountId.fromString("0.0.123-ghaha").validateChecksum(
38 | IntegrationTestEnv.forMainnet(),
39 | );
40 | } catch {
41 | err = true;
42 | }
43 |
44 | if (!err) {
45 | throw new Error("entity parsing did not err");
46 | }
47 | });
48 |
49 | afterAll(async function () {
50 | client.close();
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/test/integration/AccountRecordsIntegrationTest.js:
--------------------------------------------------------------------------------
1 | import {
2 | AccountRecordsQuery,
3 | Hbar,
4 | TransferTransaction,
5 | } from "../../src/exports.js";
6 | import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js";
7 | import { createAccount, deleteAccount } from "./utils/Fixtures.js";
8 |
9 | describe("AccountRecords", function () {
10 | let env;
11 |
12 | beforeAll(async function () {
13 | env = await IntegrationTestEnv.new();
14 | });
15 |
16 | it("should be executable", async function () {
17 | const operatorId = env.operatorId;
18 |
19 | const { accountId, newKey } = await createAccount(env.client);
20 |
21 | expect(accountId).to.not.be.null;
22 |
23 | await (
24 | await new TransferTransaction()
25 | .addHbarTransfer(accountId, new Hbar(1))
26 | .addHbarTransfer(operatorId, new Hbar(1).negated())
27 | .execute(env.client)
28 | ).getReceipt(env.client);
29 |
30 | const records = await new AccountRecordsQuery()
31 | .setAccountId(operatorId)
32 | .setMaxQueryPayment(new Hbar(1))
33 | .execute(env.client);
34 |
35 | expect(records.length).to.be.gt(0);
36 |
37 | await deleteAccount(env.client, newKey, (transaction) => {
38 | transaction
39 | .setAccountId(accountId)
40 | .setTransferAccountId(operatorId);
41 | });
42 | });
43 |
44 | afterAll(async function () {
45 | await env.close();
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/test/integration/AddressBookQueryTest.js:
--------------------------------------------------------------------------------
1 | import { AddressBookQuery } from "../../src/exports.js";
2 | import { Client } from "./client/NodeIntegrationTestEnv.js";
3 | import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js";
4 |
5 | describe("AddressBookQuery", function () {
6 | it("should be query the addressbook on local node", async function () {
7 | // NOTE: Ensure the environment is configured for local use
8 | const env = await IntegrationTestEnv.new();
9 |
10 | const addressBook = await new AddressBookQuery()
11 | .setFileId("0.0.102")
12 | .execute(env.client);
13 |
14 | expect(addressBook.nodeAddresses.length).to.be.above(0);
15 | env.client.close();
16 | });
17 |
18 | it("should be query the addressbook on testnet", async function () {
19 | const client = Client.forTestnet();
20 |
21 | const addressBook = await new AddressBookQuery()
22 | .setFileId("0.0.102")
23 | .execute(client);
24 |
25 | expect(addressBook.nodeAddresses.length).to.be.above(0);
26 | client.close();
27 | });
28 |
29 | it("should be query the addressbook on mainnet", async function () {
30 | const client = Client.forMainnet();
31 |
32 | const addressBook = await new AddressBookQuery()
33 | .setFileId("0.0.102")
34 | .execute(client);
35 |
36 | expect(addressBook.nodeAddresses.length).to.be.above(0);
37 | client.close();
38 | });
39 | });
40 |
--------------------------------------------------------------------------------
/test/integration/FreezeTransactionIntegrationTest.js:
--------------------------------------------------------------------------------
1 | import {
2 | Timestamp,
3 | FreezeTransaction,
4 | FreezeType,
5 | // TransactionResponse,
6 | // TransactionReceipt,
7 | Status,
8 | } from "../../src/exports.js";
9 | import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js";
10 |
11 | describe("FreezeTransaction", function () {
12 | let client;
13 |
14 | beforeAll(async function () {
15 | const env = await IntegrationTestEnv.new();
16 | client = env.client;
17 | });
18 |
19 | it("should be executable but not supported", async function () {
20 | const seconds = Math.round(Date.now() / 1000);
21 | const validStart = new Timestamp(seconds, 0);
22 |
23 | const transaction = new FreezeTransaction()
24 | .setStartTimestamp(validStart)
25 | .setFreezeType(new FreezeType(1))
26 | .freezeWith(client);
27 | expect(transaction.startTimestamp).to.be.equal(validStart);
28 | expect(transaction.freezeType).to.be.instanceof(FreezeType);
29 |
30 | try {
31 | await transaction.execute(client);
32 | } catch (error) {
33 | expect(error.status).to.be.equal(Status.NotSupported);
34 | }
35 |
36 | client.close();
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/test/integration/LocalWalletTest.js:
--------------------------------------------------------------------------------
1 | import { Wallet, LocalProvider } from "../../src/index.js";
2 |
3 | import dotenv from "dotenv";
4 |
5 | dotenv.config();
6 |
7 | describe("LocalWallet", function () {
8 | it("can fetch wallet's info", async function () {
9 | const wallet = new Wallet(
10 | process.env.OPERATOR_ID,
11 | process.env.OPERATOR_KEY,
12 | new LocalProvider(),
13 | );
14 |
15 | const info = await wallet.getAccountInfo();
16 |
17 | expect(info.accountId.compare(wallet.getAccountId())).to.be.equal(0);
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/test/integration/NetworkVersionInfoIntegrationTest.js:
--------------------------------------------------------------------------------
1 | import { NetworkVersionInfoQuery } from "../../src/exports.js";
2 | import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js";
3 |
4 | describe("NetworkVersionInfo", function () {
5 | let env;
6 |
7 | beforeAll(async function () {
8 | env = await IntegrationTestEnv.new();
9 | });
10 |
11 | it("should be executable", async function () {
12 | try {
13 | await new NetworkVersionInfoQuery().execute(env.client);
14 | } catch {
15 | // Do nothing
16 | }
17 | });
18 |
19 | afterAll(async function () {
20 | await env.close();
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/test/integration/TokenDeleteIntegrationTest.js:
--------------------------------------------------------------------------------
1 | import { TokenDeleteTransaction, Status } from "../../src/exports.js";
2 | import IntegrationTestEnv from "./client/NodeIntegrationTestEnv.js";
3 | import { createFungibleToken } from "./utils/Fixtures.js";
4 |
5 | describe("TokenDelete", function () {
6 | let env;
7 |
8 | beforeAll(async function () {
9 | env = await IntegrationTestEnv.new();
10 | });
11 |
12 | it("should be executable", async function () {
13 | const tokenId = await createFungibleToken(env.client);
14 |
15 | await (
16 | await new TokenDeleteTransaction()
17 | .setTokenId(tokenId)
18 | .execute(env.client)
19 | ).getReceipt(env.client);
20 | });
21 |
22 | it("should error with no token ID set", async function () {
23 | let err = false;
24 |
25 | try {
26 | await (
27 | await new TokenDeleteTransaction().execute(env.client)
28 | ).getReceipt(env.client);
29 | } catch (error) {
30 | err = error.toString().includes(Status.InvalidTokenId);
31 | }
32 |
33 | if (!err) {
34 | throw new Error("token deletion did not error");
35 | }
36 | });
37 |
38 | afterAll(async function () {
39 | await env.close();
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/test/integration/client/NodeIntegrationTestEnv.js:
--------------------------------------------------------------------------------
1 | import Wallet from "../../../src/Wallet.js";
2 | import Client from "../../../src/client/NodeClient.js";
3 | import BaseIntegrationTestEnv from "./BaseIntegrationTestEnv.js";
4 | import dotenv from "dotenv";
5 |
6 | dotenv.config();
7 |
8 | export { Client };
9 |
10 | /**
11 | * @typedef {number} minVersion
12 | */
13 | export function skipTestDueToNodeJsVersion(minVersion) {
14 | if (
15 | process == null ||
16 | process.versions == null ||
17 | process.versions.node == null ||
18 | parseInt(process.versions.node.split(".")[0]) < minVersion
19 | ) {
20 | console.log("skipping test due to unsupported nodejs version");
21 | return true;
22 | }
23 | }
24 |
25 | export default class IntegrationTestEnv extends BaseIntegrationTestEnv {
26 | /**
27 | * @param {object} [options]
28 | * @property {number} [options.nodeAccountIds]
29 | * @property {number} [options.balance]
30 | * @property {boolean} [options.throwaway]
31 | */
32 | static async new(options = {}) {
33 | return BaseIntegrationTestEnv.new({
34 | client: Client,
35 | wallet: Wallet,
36 | env: process.env,
37 | nodeAccountIds: options.nodeAccountIds,
38 | balance: options.balance,
39 | throwaway: options.throwaway,
40 | });
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/test/integration/client/TestnetIntegrationTestEnv.js:
--------------------------------------------------------------------------------
1 | import Client from "../../../src/client/NodeClient.js";
2 | import BaseIntegrationTestEnv from "./BaseIntegrationTestEnv.js";
3 |
4 | export { Client };
5 |
6 | export function skipTestDueToNodeJsVersion() {
7 | return true;
8 | }
9 |
10 | export default class TestnetIntegrationTestEnv extends BaseIntegrationTestEnv {
11 | /**
12 | * @param {object} [options]
13 | * @property {number} [options.nodeAccountIds]
14 | * @property {number} [options.balance]
15 | * @property {boolean} [options.throwaway]
16 | */
17 | static async new(options = {}) {
18 | return BaseIntegrationTestEnv.new({
19 | client: Client,
20 | env: {
21 | OPERATOR_ID: "0.0.8920",
22 | OPERATOR_KEY:
23 | "07f9f9c355d32c5c93a50024b596ed3ccc39954ba1963c68ac21cb7802fd5f83",
24 | HEDERA_NETWORK: "testnet",
25 | },
26 | nodeAccountIds: options.nodeAccountIds,
27 | balance: options.balance,
28 | throwaway: options.throwaway,
29 | });
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/test/integration/client/WebIntegrationTestEnv.js:
--------------------------------------------------------------------------------
1 | import Client from "../../src/client/WebClient.js";
2 | import BaseIntegrationTestEnv from "./BaseIntegrationTestEnv.js";
3 |
4 | export { Client };
5 |
6 | export function skipTestDueToNodeJsVersion() {
7 | return true;
8 | }
9 |
10 | export default class IntegrationTestEnv extends BaseIntegrationTestEnv {
11 | /**
12 | * @param {object} [options]
13 | * @property {number} [options.nodeAccountIds]
14 | * @property {number} [options.balance]
15 | * @property {boolean} [options.throwaway]
16 | */
17 | static async new(options = {}) {
18 | return BaseIntegrationTestEnv.new({
19 | client: Client,
20 | env: {
21 | OPERATOR_ID: "0.0.8920",
22 | OPERATOR_KEY:
23 | "07f9f9c355d32c5c93a50024b596ed3ccc39954ba1963c68ac21cb7802fd5f83",
24 | HEDERA_NETWORK: "testnet",
25 | },
26 | nodeAccountIds: options.nodeAccountIds,
27 | balance: options.balance,
28 | throwaway: options.throwaway,
29 | });
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/test/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "lib": ["ESNext", "DOM"],
6 | "typeRoots": ["../node_modules"],
7 | "types": ["vitest/globals"],
8 | "allowJs": true,
9 | "checkJs": false,
10 | "emitDeclarationOnly": true,
11 | "declaration": true,
12 | "rootDir": ".",
13 | "moduleResolution": "node",
14 | "allowSyntheticDefaultImports": true,
15 | "esModuleInterop": true
16 | },
17 | "include": ["unit", "integration"]
18 | }
19 |
--------------------------------------------------------------------------------
/test/unit/AccountAllowanceDeleteTransaction.js:
--------------------------------------------------------------------------------
1 | import {
2 | AccountAllowanceDeleteTransaction,
3 | AccountId,
4 | Transaction,
5 | TransactionId,
6 | TokenId,
7 | NftId,
8 | } from "../../src/index.js";
9 | import Long from "long";
10 |
11 | describe("AccountAllowanceDeleteTransaction", function () {
12 | it("[from|to]Bytes", async function () {
13 | const tokenId = TokenId.fromString("1.2.3");
14 | const serialNumber = Long.fromNumber(4);
15 | const operatorId = AccountId.fromString("5.6.7");
16 | const nftId = new NftId(tokenId, serialNumber);
17 | const transactionId = TransactionId.fromString(
18 | `${operatorId.toString()}@8.9`,
19 | );
20 | const nodeAccountId = AccountId.fromString("10.11.12");
21 | const transaction = new AccountAllowanceDeleteTransaction()
22 | .setNodeAccountIds([nodeAccountId])
23 | .setTransactionId(transactionId)
24 | .deleteAllTokenNftAllowances(nftId, operatorId)
25 | .freeze();
26 |
27 | const bytes = transaction.toBytes();
28 | Transaction.fromBytes(bytes);
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/test/unit/AccountInfoQuery.js:
--------------------------------------------------------------------------------
1 | import { AccountId, Query, AccountInfoQuery } from "../../src/index.js";
2 |
3 | describe("AccountInfo", function () {
4 | it("[to|from]Bytes()", async function () {
5 | const accountId = new AccountId(10);
6 |
7 | const query = Query.fromBytes(
8 | new AccountInfoQuery().setAccountId(accountId).toBytes(),
9 | );
10 |
11 | expect(query instanceof AccountInfoQuery).to.be.true;
12 |
13 | expect(query.accountId.toString()).to.be.equal(accountId.toString());
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/test/unit/AccountUpdateTransaction.js:
--------------------------------------------------------------------------------
1 | import { AccountUpdateTransaction } from "../../src/index.js";
2 |
3 | describe("AccountUpdateTransaction", function () {
4 | describe("deserialization of optional parameters", function () {
5 | let tx, txBytes, tx2;
6 |
7 | beforeAll(function () {
8 | tx = new AccountUpdateTransaction();
9 | txBytes = tx.toBytes();
10 | tx2 = AccountUpdateTransaction.fromBytes(txBytes);
11 | });
12 |
13 | it("should deserialize with accountMemo being null", function () {
14 | expect(tx.accountMemo).to.be.null;
15 | expect(tx2.accountMemo).to.be.null;
16 | });
17 |
18 | it("should deserialize with declineReward, receiverSignatureRequired being null", function () {
19 | expect(tx.declineStakingRewards).to.be.null;
20 | expect(tx2.declineStakingRewards).to.be.null;
21 |
22 | expect(tx.receiverSignatureRequired).to.be.null;
23 | expect(tx2.receiverSignatureRequired).to.be.null;
24 | });
25 |
26 | it("should deserialize with maxAutomaticTokenAssociations being null", function () {
27 | expect(tx.maxAutomaticTokenAssociations).to.be.null;
28 | expect(tx2.maxAutomaticTokenAssociations).to.be.null;
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/test/unit/AirdropCancelTransaction.js:
--------------------------------------------------------------------------------
1 | import { AccountId, TokenId } from "../../src/exports.js";
2 | import TokenCancelAirdropTransaction from "../../src/token/TokenCancelAirdropTransaction.js";
3 | import PendingAirdropId from "../../src/token/PendingAirdropId.js";
4 |
5 | describe("TokenAirdropCancelTransaction", function () {
6 | it("from | to bytes", async function () {
7 | const pendingAirdropId = new PendingAirdropId({
8 | tokenId: new TokenId(0, 0, 123),
9 | serial: 456,
10 | senderId: new AccountId(0, 0, 789),
11 | receiverId: new AccountId(0, 0, 987),
12 | });
13 |
14 | const tx = new TokenCancelAirdropTransaction({
15 | pendingAirdropIds: [pendingAirdropId],
16 | });
17 |
18 | const tx2 = TokenCancelAirdropTransaction.fromBytes(tx.toBytes());
19 |
20 | expect(tx2.pendingAirdropIds[0]).to.deep.equal(pendingAirdropId);
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/test/unit/AirdropClaimTransaction.js:
--------------------------------------------------------------------------------
1 | import { AccountId, TokenId } from "../../src/exports.js";
2 | import TokenClaimAirdropTransaction from "../../src/token/TokenClaimAirdropTransaction.js";
3 | import PendingAirdropId from "../../src/token/PendingAirdropId.js";
4 |
5 | describe("TokenClaimAirdropTransaction", function () {
6 | it("from | to bytes", async function () {
7 | const pendingAirdropId = new PendingAirdropId({
8 | tokenId: new TokenId(0, 0, 123),
9 | serial: 456,
10 | senderId: new AccountId(0, 0, 789),
11 | receiverId: new AccountId(0, 0, 987),
12 | });
13 | const tx = new TokenClaimAirdropTransaction({
14 | pendingAirdropIds: [pendingAirdropId],
15 | });
16 |
17 | const tx2 = TokenClaimAirdropTransaction.fromBytes(tx.toBytes());
18 |
19 | expect(tx2.pendingAirdropIds[0]).to.deep.equal(pendingAirdropId);
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/unit/ContractNonceInfo.js:
--------------------------------------------------------------------------------
1 | import { ContractId, ContractNonceInfo } from "../../src/exports.js";
2 |
3 | describe("ContractNonceInfo", function () {
4 | it("provides nonce correctly", async function () {
5 | const info = new ContractNonceInfo({
6 | contractId: ContractId.fromString("1.2.3"),
7 | nonce: 2,
8 | });
9 |
10 | const contractId = {
11 | shardNum: 1,
12 | realmNum: 2,
13 | contractNum: 3,
14 | evmAddress: null,
15 | };
16 |
17 | expect(info.contractId.shard.toNumber()).to.be.equal(
18 | contractId.shardNum,
19 | );
20 | expect(info.contractId.realm.toNumber()).to.be.equal(
21 | contractId.realmNum,
22 | );
23 | expect(info.contractId.num.toNumber()).to.be.equal(
24 | contractId.contractNum,
25 | );
26 | expect(info.contractId.evmAddress).to.be.equal(contractId.evmAddress);
27 | expect(info.nonce).to.be.equal(2);
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/test/unit/CustomFeeLimit.js:
--------------------------------------------------------------------------------
1 | import {
2 | AccountId,
3 | CustomFeeLimit,
4 | CustomFixedFee,
5 | TokenId,
6 | } from "../../src/index.js";
7 |
8 | describe("CustomFeeLimit", function () {
9 | it("should set the correct account id", function () {
10 | const accountId = new AccountId(0, 0, 2);
11 | const customFeeLimit = new CustomFeeLimit().setAccountId(accountId);
12 |
13 | expect(customFeeLimit.getAccountId().toString()).to.eql(
14 | accountId.toString(),
15 | );
16 | });
17 |
18 | it("should set the correct custom fixed fees", function () {
19 | const tokenId = new TokenId(0);
20 |
21 | const amount = 100;
22 |
23 | const fixedFee = new CustomFixedFee()
24 | .setAmount(amount)
25 | .setDenominatingTokenId(tokenId);
26 |
27 | const customFeeLimit = new CustomFeeLimit().setFees([fixedFee]);
28 |
29 | expect(customFeeLimit.getFees()[0].amount.toString()).to.eql(
30 | amount.toString(),
31 | );
32 |
33 | expect(
34 | customFeeLimit.getFees()[0].denominatingTokenId.toString(),
35 | ).to.eql(tokenId.toString());
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/test/unit/DelegateContractId.js:
--------------------------------------------------------------------------------
1 | import { ContractId, DelegateContractId, Key } from "../../src/index.js";
2 | import Long from "long";
3 |
4 | describe("DelegateContractId", function () {
5 | it("constructors", function () {
6 | expect(() => new DelegateContractId(3)).to.not.throw();
7 | expect(() => new DelegateContractId(0, 0, 3)).to.not.throw();
8 | expect(
9 | () => new DelegateContractId({ shard: 0, realm: 0, num: 3 }),
10 | ).to.not.throw();
11 | });
12 |
13 | it(".[to|from]Protobuf()", function () {
14 | const id = new DelegateContractId(1, 2, 3);
15 | const idProto = {
16 | shardNum: Long.fromNumber(1),
17 | realmNum: Long.fromNumber(2),
18 | contractNum: Long.fromNumber(3),
19 | evmAddress: null,
20 | };
21 | const idProtoKey = {
22 | delegatableContractId: idProto,
23 | };
24 | const keyToId = Key._fromProtobufKey(idProtoKey);
25 |
26 | expect(id.toString()).to.be.equal("1.2.3");
27 |
28 | expect(id._toProtobuf()).to.deep.equal(idProto);
29 | expect(id._toProtobufKey()).to.deep.equal(idProtoKey);
30 | expect(
31 | DelegateContractId._fromProtobuf(idProto).toString(),
32 | ).to.deep.equal("1.2.3");
33 | expect(keyToId.toString()).to.deep.equal("1.2.3");
34 | expect(keyToId instanceof DelegateContractId).to.be.true;
35 | expect(keyToId instanceof ContractId).to.be.true;
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/test/unit/ExchangeRate.js:
--------------------------------------------------------------------------------
1 | import { ExchangeRate } from "../../src/index.js";
2 |
3 | describe("ExchangeRate", function () {
4 | it("fromBytes", function () {
5 | const date = new Date("February 24, 2022 15:00:00 UTC");
6 | const exchangeRate = ExchangeRate._fromProtobuf(
7 | new ExchangeRate({
8 | expirationTime: date,
9 | })._toProtobuf(),
10 | );
11 |
12 | expect(exchangeRate.expirationTime.toString()).to.be.equal(
13 | date.toString(),
14 | );
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/test/unit/Executable.js:
--------------------------------------------------------------------------------
1 | import { RST_STREAM } from "../../src/Executable.js";
2 |
3 | describe("Executable", function () {
4 | it("RST_STREAM regex matches actual response returned", function () {
5 | expect(
6 | RST_STREAM.test(
7 | "Error: 13 INTERNAL: Received RST_STREAM with code 0",
8 | ),
9 | ).to.be.true;
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/test/unit/FeeDataType.js:
--------------------------------------------------------------------------------
1 | import * as HieroProto from "@hashgraph/proto";
2 | import { FeeDataType } from "../../src/exports.js";
3 |
4 | describe("FeeDataType", function () {
5 | it("has all variants", function () {
6 | for (const [s, code] of Object.entries(HieroProto.proto.SubType)) {
7 | expect(FeeDataType._fromCode(code).toString()).to.be.equal(s);
8 | }
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/test/unit/FileUpdateTransaction.js:
--------------------------------------------------------------------------------
1 | import { FileUpdateTransaction } from "../../src/index.js";
2 |
3 | describe("FileUpdateTransaction", function () {
4 | describe("deserialization of optional parameters", function () {
5 | it("should deserialize with fileMemo being null", function () {
6 | const tx = new FileUpdateTransaction();
7 | const tx2 = FileUpdateTransaction.fromBytes(tx.toBytes());
8 |
9 | expect(tx.fileMemo).to.be.null;
10 | expect(tx2.fileMemo).to.be.null;
11 | });
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/test/unit/HbarAllowance.js:
--------------------------------------------------------------------------------
1 | import { HbarAllowance, AccountId, Hbar } from "../../src/index.js";
2 |
3 | describe("HbarAllowance", function () {
4 | it("toProtobuf()", function () {
5 | const ownerAccountId = new AccountId(3);
6 | const spenderAccountId = new AccountId(4);
7 | const hbarAmount = Hbar.fromTinybars(100);
8 |
9 | const allowance = new HbarAllowance({
10 | ownerAccountId,
11 | spenderAccountId,
12 | amount: hbarAmount,
13 | });
14 |
15 | expect(allowance._toProtobuf()).to.deep.equal({
16 | owner: ownerAccountId._toProtobuf(),
17 | spender: spenderAccountId._toProtobuf(),
18 | amount: hbarAmount.toTinybars(),
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/unit/MirrorNodeContractCallQuery.js:
--------------------------------------------------------------------------------
1 | import { AccountId, MirrorNodeContractCallQuery } from "../../src/exports.js";
2 |
3 | describe("MirrorNodeContractCallQuery", function () {
4 | const SENDER = new AccountId(1);
5 | const CONTRACT_ID = new AccountId(1);
6 | const VALUE = 100;
7 | const GAS_LIMIT = 100;
8 | const GAS_PRICE = 100;
9 | const BLOCK_NUMBER = 100;
10 |
11 | it("should throw an error without calldata", async function () {
12 | const query = new MirrorNodeContractCallQuery()
13 | .setBlockNumber(BLOCK_NUMBER)
14 | .setSender(SENDER)
15 | .setValue(VALUE)
16 | .setGasLimit(GAS_LIMIT)
17 | .setGasPrice(GAS_PRICE)
18 | .setContractId(CONTRACT_ID);
19 |
20 | let err = false;
21 | try {
22 | await query.execute();
23 | } catch (e) {
24 | err = e.message.includes("Call data is required.");
25 | }
26 | expect(err).to.equal(true);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/test/unit/MirrorNodeContractEstimateQuery.js:
--------------------------------------------------------------------------------
1 | import {
2 | AccountId,
3 | MirrorNodeContractEstimateQuery,
4 | } from "../../src/exports.js";
5 |
6 | describe("MirrorNodeContractCallQuery", function () {
7 | const SENDER = new AccountId(1);
8 | const CONTRACT_ID = new AccountId(1);
9 | const VALUE = 100;
10 | const GAS_LIMIT = 100;
11 | const GAS_PRICE = 100;
12 | const BLOCK_NUMBER = 100;
13 |
14 | it("should throw an error without calldata", async function () {
15 | const query = new MirrorNodeContractEstimateQuery()
16 | .setBlockNumber(BLOCK_NUMBER)
17 | .setSender(SENDER)
18 | .setValue(VALUE)
19 | .setGasLimit(GAS_LIMIT)
20 | .setGasPrice(GAS_PRICE)
21 | .setContractId(CONTRACT_ID);
22 |
23 | let err = false;
24 | try {
25 | await query.execute();
26 | } catch (e) {
27 | err = e.message.includes("Call data is required.");
28 | }
29 | expect(err).to.equal(true);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/test/unit/NodeDeleteTransaction.js:
--------------------------------------------------------------------------------
1 | import {
2 | AccountId,
3 | Hbar,
4 | NodeDeleteTransaction,
5 | Timestamp,
6 | TransactionId,
7 | } from "../../src/index.js";
8 |
9 | describe("NodeDeleteTransaction", function () {
10 | let tx;
11 |
12 | beforeEach(function () {
13 | const NODE_ID = 420,
14 | VALID_START = new Timestamp(1596210382, 0);
15 |
16 | tx = new NodeDeleteTransaction()
17 | .setNodeAccountIds([
18 | AccountId.fromString("0.0.5005"),
19 | AccountId.fromString("0.0.5006"),
20 | ])
21 | .setTransactionId(
22 | TransactionId.withValidStart(
23 | AccountId.fromString("0.0.5006"),
24 | VALID_START,
25 | ),
26 | )
27 | .setNodeId(NODE_ID)
28 | .setMaxTransactionFee(new Hbar(1));
29 | });
30 |
31 | it("should convert from and to bytes", function () {
32 | const tx2 = NodeDeleteTransaction.fromBytes(tx.toBytes());
33 | tx.nodeAccountIds.forEach((_, index) => {
34 | expect(tx.nodeAccountIds[index].toString()).to.equal(
35 | tx2.nodeAccountIds[index].toString(),
36 | );
37 | });
38 | expect(tx.transactionId.toString()).to.equal(
39 | tx2.transactionId.toString(),
40 | );
41 | });
42 |
43 | it("should return node id", function () {
44 | expect(tx.nodeId).to.equal(420);
45 | });
46 |
47 | it("should set node id", function () {
48 | tx.setNodeId(421);
49 | expect(tx.nodeId).to.equal(421);
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/test/unit/PrngTransaction.js:
--------------------------------------------------------------------------------
1 | import {
2 | PrngTransaction,
3 | Transaction,
4 | AccountId,
5 | Timestamp,
6 | TransactionId,
7 | } from "../../src/index.js";
8 |
9 | describe("PrngTransaction", function () {
10 | it("should return range when create transaction from Bytes", async function () {
11 | const spenderAccountId = new AccountId(1);
12 | const timestamp = new Timestamp(14, 15);
13 |
14 | let transaction = await new PrngTransaction()
15 | .setTransactionId(
16 | TransactionId.withValidStart(spenderAccountId, timestamp),
17 | )
18 | .setNodeAccountIds([spenderAccountId])
19 | .setRange(100)
20 | .freeze();
21 |
22 | const transactionToBytes = transaction.toBytes();
23 |
24 | const transactionFromBytes = Transaction.fromBytes(transactionToBytes);
25 |
26 | expect(transactionFromBytes.range).to.eql(100);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/test/unit/RequestType.js:
--------------------------------------------------------------------------------
1 | import * as HieroProto from "@hashgraph/proto";
2 | import { RequestType } from "../../src/exports.js";
3 |
4 | describe("RequestType", function () {
5 | it("has all the response codes", function () {
6 | for (const [s, code] of Object.entries(
7 | HieroProto.proto.HederaFunctionality,
8 | )) {
9 | expect(RequestType._fromCode(code).toString()).to.be.equal(s);
10 | }
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/test/unit/Status.js:
--------------------------------------------------------------------------------
1 | import * as HieroProto from "@hashgraph/proto";
2 | import { Status } from "../../src/exports.js";
3 |
4 | describe("Status", function () {
5 | it("has all the response codes", function () {
6 | for (const [s, code] of Object.entries(
7 | HieroProto.proto.ResponseCodeEnum,
8 | )) {
9 | expect(Status._fromCode(code).toString()).to.be.equal(s);
10 | }
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/test/unit/Timestamp.js:
--------------------------------------------------------------------------------
1 | import { Timestamp } from "../../src/index.js";
2 |
3 | describe("Timestamp", function () {
4 | it("plusNanos works correctly", async function () {
5 | let timestamp = new Timestamp(0, 999999998);
6 |
7 | expect(timestamp.seconds.toInt()).to.be.eql(0);
8 | expect(timestamp.nanos.toInt()).to.be.eql(999999998);
9 |
10 | timestamp = timestamp.plusNanos(1);
11 |
12 | expect(timestamp.seconds.toInt()).to.be.eql(0);
13 | expect(timestamp.nanos.toInt()).to.be.eql(999999999);
14 |
15 | timestamp = timestamp.plusNanos(1);
16 |
17 | expect(timestamp.seconds.toInt()).to.be.eql(1);
18 | expect(timestamp.nanos.toInt()).to.be.eql(0);
19 |
20 | timestamp = timestamp.plusNanos(1);
21 |
22 | expect(timestamp.seconds.toInt()).to.be.eql(1);
23 | expect(timestamp.nanos.toInt()).to.be.eql(1);
24 | });
25 |
26 | it("fromDate()", function () {
27 | let timestamp = Timestamp.fromDate(999999998);
28 |
29 | expect(timestamp.seconds.toInt()).to.be.eql(0);
30 | expect(timestamp.nanos.toInt()).to.be.eql(999999998);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/test/unit/TokenAllowance.js:
--------------------------------------------------------------------------------
1 | import { TokenAllowance, AccountId, TokenId } from "../../src/index.js";
2 | import Long from "long";
3 |
4 | describe("TokenAllowance", function () {
5 | it("toProtobuf()", function () {
6 | const ownerAccountId = new AccountId(3);
7 | const tokenId = new TokenId(1);
8 | const spenderAccountId = new AccountId(4);
9 | const tokenAmount = Long.fromNumber(100);
10 |
11 | const allowance = new TokenAllowance({
12 | ownerAccountId,
13 | tokenId,
14 | spenderAccountId,
15 | amount: tokenAmount,
16 | });
17 |
18 | expect(allowance._toProtobuf()).to.deep.equal({
19 | owner: ownerAccountId._toProtobuf(),
20 | tokenId: tokenId._toProtobuf(),
21 | spender: spenderAccountId._toProtobuf(),
22 | amount: tokenAmount,
23 | });
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/test/unit/TokenTransfer.js:
--------------------------------------------------------------------------------
1 | import TokenTransfer from "../../src/token/TokenTransfer.js";
2 |
3 | describe("TokenTransfer", function () {
4 | describe("_fromProtobuf with optional parameters", function () {
5 | it("should deserialize with expectedDecimals being null", function () {
6 | const transfer = new TokenTransfer({
7 | tokenId: "0.0.123",
8 | accountId: "0.0.456",
9 | amount: 100,
10 | expectedDecimals: null,
11 | isApproved: true,
12 | });
13 |
14 | const transfersProtobuf = [
15 | {
16 | token: transfer.tokenId._toProtobuf(),
17 | expectedDecimals: {},
18 | transfers: [transfer._toProtobuf()],
19 | },
20 | ];
21 |
22 | const [transferFromProtobuf] =
23 | TokenTransfer._fromProtobuf(transfersProtobuf);
24 |
25 | expect(transferFromProtobuf.expectedDecimals).to.be.null;
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/test/unit/TransactionResponse.js:
--------------------------------------------------------------------------------
1 | import {
2 | AccountId,
3 | TransactionId,
4 | TransactionResponse,
5 | } from "../../src/index.js";
6 |
7 | describe("TransactionResponse", function () {
8 | it("toJSON()", function () {
9 | const response = new TransactionResponse({
10 | nodeId: AccountId.fromString("0.0.3"),
11 | transactionHash: Uint8Array.of(1, 2, 3),
12 | transactionId: TransactionId.fromString("0.0.12@13.000000014"),
13 | });
14 |
15 | const expectedJSON = `{"nodeId":"0.0.3","transactionHash":"010203","transactionId":"0.0.12@13.000000014"}`;
16 | const expectedJSONParsed = JSON.parse(expectedJSON);
17 |
18 | const resultJSON = JSON.parse(JSON.stringify(response));
19 | expect(resultJSON).to.deep.equal(expectedJSONParsed);
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/test/unit/keccak256.js:
--------------------------------------------------------------------------------
1 | import { keccak256 } from "../../src/cryptography/keccak.js";
2 | import * as hex from "../../src/encoding/hex.js";
3 |
4 | describe("keccak256", function () {
5 | it("should hash to the expected value", function () {
6 | const hash = keccak256("method");
7 |
8 | expect(hash).to.eql(
9 | "0x9c87604675c4160b0aac6ee753604a7ebe1728c804a0ac841ff8bb02e543aa3a",
10 | );
11 | });
12 |
13 | it("should hash to the expected value for bytes larger than 127", function () {
14 | const hash = keccak256(
15 | hex.decode("0x00112233445566778899aabbccddeeff"),
16 | );
17 |
18 | expect(hash).to.eql(
19 | "0x22bce46032802af0abfacf3768f7be04a34f5f01df60f44ffd52d3ca937350c0",
20 | );
21 | });
22 |
23 | it("should hash body bytes correctly", function () {
24 | const hash = keccak256(
25 | hex.decode(
26 | "0x0a0e0a0408011001120608001000180412060800100018031880c2d72f220208783200721a0a180a0a0a0608001000180410130a0a0a060800100018051014",
27 | ),
28 | );
29 |
30 | expect(hash).to.eql(
31 | "0x90c1c5bb75d76d3cfed2c136525ffbcf381b4b3909cefd11b68b26ce6f9999b6",
32 | );
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/test/vitest-node-integration.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vitest/config";
2 |
3 | import path from "path";
4 | import fs from "fs";
5 |
6 | const pkg = JSON.parse(
7 | fs.readFileSync(path.resolve(__dirname, "../package.json"), "utf-8"),
8 | );
9 |
10 | /** @type {import("vitest").UserConfig} */
11 | export default defineConfig({
12 | test: {
13 | watch: false,
14 | globals: true,
15 | environment: "node",
16 | include: ["test/integration/**/*.js"],
17 | exclude: [
18 | "test/integration/client/*",
19 | "test/integration/resources/*",
20 | "test/integration/utils/*",
21 | "test/integration/contents.js",
22 | ],
23 | hookTimeout: 120000,
24 | testTimeout: 120000,
25 | maxWorkers: 4,
26 | minWorkers: 4,
27 | coverage: {
28 | include: ["src/**/*.js"],
29 | provider: "v8",
30 | reporter: ["text-summary", "lcov"],
31 | reportsDirectory: "./coverage",
32 | },
33 | },
34 | define: {
35 | __SDK_VERSION__: JSON.stringify(pkg.version),
36 | },
37 | });
38 |
--------------------------------------------------------------------------------
/test/vitest-node.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vitest/config";
2 |
3 | /** @type {import("vitest").UserConfig} */
4 | export default defineConfig({
5 | test: {
6 | watch: false,
7 | globals: true,
8 | environment: "node",
9 | include: ["test/unit/**/*.js"],
10 | exclude: ["test/unit/Mocker.js", "test/unit/browser/*"],
11 | testTimeout: 120000,
12 | coverage: {
13 | include: ["src/**/*.js"],
14 | provider: "v8",
15 | reporter: ["text-summary", "lcov"],
16 | reportsDirectory: "./coverage",
17 | },
18 | },
19 | });
20 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "lib": ["ESNext", "DOM"],
6 | "allowJs": true,
7 | "checkJs": true,
8 | "emitDeclarationOnly": true,
9 | "outDir": "lib/",
10 | "declaration": true,
11 | "rootDir": "src/",
12 | "strict": true,
13 | "noImplicitAny": true,
14 | "noUnusedLocals": true,
15 | "noUnusedParameters": false,
16 | "downlevelIteration": true,
17 | "noImplicitReturns": true,
18 | "noFallthroughCasesInSwitch": true,
19 | "moduleResolution": "node",
20 | "allowSyntheticDefaultImports": true,
21 | "esModuleInterop": true,
22 | "forceConsistentCasingInFileNames": true
23 | },
24 | "include": ["src"]
25 | }
26 |
--------------------------------------------------------------------------------
/typedoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://typedoc.org/schema.json",
3 | "entryPoints": ["./src/index.js", "./src/browser.ts", "./src/native.js"],
4 | "out": "docs"
5 | }
6 |
--------------------------------------------------------------------------------
/update_protos.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | cd packages/proto/src/proto/
3 | git pull origin main
4 | cd ../..
5 | pnpm i
6 | pnpm compile
7 | pnpm format
8 | pnpm lint
9 | cd ../..
10 | pnpm add link:packages/proto
11 | pnpm add link:packages/proto
12 | pnpm i
13 | pnpm compile
14 | pnpm format
15 | pnpm lint
16 |
--------------------------------------------------------------------------------