├── .babelrc.json ├── .editorconfig ├── .env.sample ├── .eslintrc.cjs ├── .github ├── CODEOWNERS ├── codecov.yaml ├── dependabot.yml └── workflows │ ├── build.yml │ ├── common_js.yml │ ├── pages.yml │ ├── pr_check.yml │ ├── publish_release.yaml │ ├── react_native.yml │ └── renovate.yml ├── .gitignore ├── .gitmodules ├── .npmrc ├── .nycrc ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── MAINTAINERS.md ├── README.md ├── Taskfile.yml ├── build └── replace-module-paths.cjs ├── check_yalc_dep.sh ├── common_js_test ├── Taskfile.yml ├── package.json ├── pnpm-lock.yaml └── src │ └── test.js ├── examples ├── .env ├── .env.example ├── .eslintrc.cjs ├── .gitignore ├── ContractHelper.js ├── Taskfile.yml ├── account-alias.js ├── account-allowance.js ├── account-create-with-hts.js ├── account-creation-ways.js ├── batch-tx.js ├── change-or-remove-token-keys.js ├── consensus-pub-sub.js ├── contract-nonces.js ├── create-account-with-alias-and-receiver-signature.js ├── create-account-with-alias.js ├── create-account-with-thresholdkey.js ├── create-account.js ├── create-contract-with-value.js ├── create-simple-contract.js ├── create-stateful-contract.js ├── create-topic-with-revenue.js ├── create-topic.js ├── create-update-delete-node.js ├── custom-grpc-web-proxies-network │ ├── .env.sample │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── pnpm-lock.yaml │ ├── public │ │ └── index.html │ └── src │ │ ├── App.js │ │ ├── index.css │ │ └── index.js ├── delete-account.js ├── demo-umd │ ├── bouncing-circles.svg │ ├── builder.png │ ├── demo.css │ ├── demo.html │ └── main.js ├── ecrecover-example.js ├── ecrecover-mirror-node-example.js ├── ecrecover_caller.json ├── ecrecover_caller.sol ├── error-handling-example.js ├── error-handling-single-node-execution.js ├── exempt-custom-fees.js ├── file-append-chunked.js ├── generate-key.js ├── generate-txid-on-demand.js ├── get-account-balance.js ├── get-account-info.js ├── get-address-book.js ├── get-exchangerates.js ├── get-file-contents.js ├── hello_world.json ├── hello_world.sol ├── hts-nftP1-fee-create-mint-burn-associate-transfer.js ├── hts-nftP2-kyc-upate-schedule.js ├── hts-nftP3-pause-freeze-wipe-delete.js ├── initialize-client-with-mirror-node-adress-book.js ├── lazy-create-transfer-tx.js ├── legacy-way-sign-transaction.js ├── local-wallet-info-query.js ├── local-wallet-sign-transaction.js ├── logger-functionalities.js ├── long-term-schedule-transaction.js ├── mint-big-number-of-units-of-token.js ├── mirror-node-contract-queries-example.js ├── multi-node-multi-signature-remove.js ├── multi-node-multi-signature-removeAll.js ├── multi-node-multi-signature.js ├── multi-sig-offline.js ├── nft-add-remove-allowances.js ├── package.json ├── payable.json ├── payable.sol ├── pnpm-lock.yaml ├── precompile-example │ ├── ExpiryHelper.sol │ ├── FeeHelper.sol │ ├── HederaResponseCodes.sol │ ├── HederaTokenService.sol │ ├── IHederaTokenService.sol │ ├── IPrngSystemContract.sol │ ├── KeyHelper.sol │ ├── PrecompileExample.json │ ├── PrecompileExample.sol │ ├── PrngSystemContract.sol │ ├── ZeroTokenOperations.json │ └── ZeroTokenOperations.sol ├── prng-transaction.js ├── react-native-example │ ├── .expo-shared │ │ └── assets.json │ ├── .gitignore │ ├── App.tsx │ ├── app.json │ ├── assets │ │ ├── adaptive-icon.png │ │ ├── favicon.png │ │ ├── icon.png │ │ └── splash.png │ ├── babel.config.js │ ├── package.json │ ├── tsconfig.json │ └── yarn.lock ├── run-all-examples.js ├── schedule-example.js ├── schedule-network-update.js ├── scheduled-transaction-multi-sig-threshold.js ├── serialize-deserialize-1.js ├── serialize-deserialize-10.js ├── serialize-deserialize-11.js ├── serialize-deserialize-12.js ├── serialize-deserialize-2.js ├── serialize-deserialize-3.js ├── serialize-deserialize-4.js ├── serialize-deserialize-5.js ├── serialize-deserialize-6.js ├── serialize-deserialize-7.js ├── serialize-deserialize-8.js ├── serialize-deserialize-9.js ├── sign-transaction.js ├── sign-tx-body-bytes-with-hsm.js ├── simple_rest_signature_provider │ ├── .env │ ├── Taskfile.yml │ ├── eslint.config.mjs │ ├── package.json │ ├── pnpm-lock.yaml │ ├── src │ │ ├── client.js │ │ └── server.js │ └── tsconfig.json ├── solidity-precompile-example.js ├── staking-example-1.js ├── staking-example-2.js ├── stateful.json ├── stateful.sol ├── time-drift.js ├── token-airdrop-example.js ├── token-reject.js ├── topic-message-submit-get-all-chunks-status.js ├── transfer-tokens.js ├── transfer-using-evm-address.js ├── tsconfig.json ├── update-fungible-token-metadata-with-admin-key.js ├── update-fungible-token-metadata-with-metadata-key.js ├── update-nfts-metadata-of-non-fungible-token.js └── zeroTokenOperations.js ├── manual ├── CONFIGURATION.md ├── MIGRATING_SIGN_TRANSACTION.md ├── MIGRATING_V1.md └── RELEASE.md ├── package.json ├── packages ├── cryptography │ ├── .babelrc.json │ ├── .eslintrc.cjs │ ├── Taskfile.yml │ ├── build │ │ └── replace-module-paths.cjs │ ├── package.json │ ├── pnpm-lock.yaml │ ├── src │ │ ├── BadKeyError.js │ │ ├── BadMnemonicError.js │ │ ├── BadMnemonicReason.js │ │ ├── Cache.js │ │ ├── EcdsaPrivateKey.js │ │ ├── EcdsaPublicKey.js │ │ ├── Ed25519PrivateKey.js │ │ ├── Ed25519PublicKey.js │ │ ├── Key.js │ │ ├── KeyList.js │ │ ├── Mnemonic.js │ │ ├── PrivateKey.js │ │ ├── PublicKey.js │ │ ├── encoding │ │ │ ├── base64.browser.js │ │ │ ├── base64.js │ │ │ ├── base64.native.js │ │ │ ├── der.js │ │ │ ├── hex.browser.js │ │ │ ├── hex.js │ │ │ ├── hex.native.js │ │ │ ├── pem.js │ │ │ ├── utf8.browser.js │ │ │ ├── utf8.js │ │ │ └── utf8.native.js │ │ ├── index.js │ │ ├── index.native.js │ │ ├── polyfills.native.js │ │ ├── primitive │ │ │ ├── aes.browser.js │ │ │ ├── aes.js │ │ │ ├── aes.native.js │ │ │ ├── bip32.js │ │ │ ├── bip39.js │ │ │ ├── ecdsa.js │ │ │ ├── hmac.browser.js │ │ │ ├── hmac.js │ │ │ ├── hmac.native.js │ │ │ ├── keccak.js │ │ │ ├── keystore.js │ │ │ ├── pbkdf2.browser.js │ │ │ ├── pbkdf2.js │ │ │ ├── pbkdf2.native.js │ │ │ ├── pkcs.js │ │ │ ├── random.js │ │ │ ├── sha256.browser.js │ │ │ ├── sha256.js │ │ │ ├── sha256.native.js │ │ │ ├── slip10.js │ │ │ └── utils.js │ │ ├── util │ │ │ ├── array.js │ │ │ ├── derive.js │ │ │ └── entropy.js │ │ └── words │ │ │ ├── bip39.js │ │ │ └── legacy.js │ ├── test │ │ ├── .eslintrc.cjs │ │ ├── node_modules │ │ ├── src │ │ ├── tsconfig.json │ │ ├── unit │ │ │ ├── EcdsaPrivateKey.js │ │ │ ├── KeyList.js │ │ │ ├── Mnemonic.js │ │ │ ├── PublicKey.js │ │ │ ├── bip39.js │ │ │ ├── encoding │ │ │ │ ├── base64.js │ │ │ │ ├── der.js │ │ │ │ ├── hex-native.js │ │ │ │ ├── hex.js │ │ │ │ ├── utf8-native.js │ │ │ │ └── utf8.js │ │ │ ├── key.js │ │ │ ├── keystore.js │ │ │ └── primitive │ │ │ │ ├── aes.browser.js │ │ │ │ ├── aes.native.js │ │ │ │ └── pkcs.js │ │ ├── vitest-browser.config.ts │ │ └── vitest-node.config.ts │ └── tsconfig.json └── proto │ ├── .babelrc.json │ ├── .eslintignore │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── .prettierrc.json │ ├── Taskfile.yml │ ├── package.json │ ├── pnpm-lock.yaml │ ├── src │ ├── index.d.ts │ ├── index.js │ └── proto │ │ ├── mirror │ │ ├── consensus_service.proto │ │ └── mirror_network_service.proto │ │ ├── sdk │ │ └── transaction_list.proto │ │ ├── services │ │ ├── address_book_service.proto │ │ ├── auxiliary │ │ │ ├── hints │ │ │ │ ├── crs_publication.proto │ │ │ │ ├── hints_key_publication.proto │ │ │ │ ├── hints_partial_signature.proto │ │ │ │ └── hints_preprocessing_vote.proto │ │ │ ├── history │ │ │ │ ├── history_proof_key_publication.proto │ │ │ │ ├── history_proof_signature.proto │ │ │ │ └── history_proof_vote.proto │ │ │ └── tss │ │ │ │ ├── tss_encryption_key.proto │ │ │ │ ├── tss_message.proto │ │ │ │ └── tss_vote.proto │ │ ├── basic_types.proto │ │ ├── consensus_create_topic.proto │ │ ├── consensus_delete_topic.proto │ │ ├── consensus_get_topic_info.proto │ │ ├── consensus_service.proto │ │ ├── consensus_submit_message.proto │ │ ├── consensus_topic_info.proto │ │ ├── consensus_update_topic.proto │ │ ├── contract_call.proto │ │ ├── contract_call_local.proto │ │ ├── contract_create.proto │ │ ├── contract_delete.proto │ │ ├── contract_get_bytecode.proto │ │ ├── contract_get_info.proto │ │ ├── contract_get_records.proto │ │ ├── contract_types.proto │ │ ├── contract_update.proto │ │ ├── crypto_add_live_hash.proto │ │ ├── crypto_approve_allowance.proto │ │ ├── crypto_create.proto │ │ ├── crypto_delete.proto │ │ ├── crypto_delete_allowance.proto │ │ ├── crypto_delete_live_hash.proto │ │ ├── crypto_get_account_balance.proto │ │ ├── crypto_get_account_records.proto │ │ ├── crypto_get_info.proto │ │ ├── crypto_get_live_hash.proto │ │ ├── crypto_get_stakers.proto │ │ ├── crypto_service.proto │ │ ├── crypto_transfer.proto │ │ ├── crypto_update.proto │ │ ├── custom_fees.proto │ │ ├── duration.proto │ │ ├── ethereum_transaction.proto │ │ ├── event_consensus_data.proto │ │ ├── event_core.proto │ │ ├── event_descriptor.proto │ │ ├── event_transaction.proto │ │ ├── exchange_rate.proto │ │ ├── file_append.proto │ │ ├── file_create.proto │ │ ├── file_delete.proto │ │ ├── file_get_contents.proto │ │ ├── file_get_info.proto │ │ ├── file_service.proto │ │ ├── file_update.proto │ │ ├── freeze.proto │ │ ├── freeze_service.proto │ │ ├── freeze_type.proto │ │ ├── get_account_details.proto │ │ ├── get_by_key.proto │ │ ├── get_by_solidity_id.proto │ │ ├── gossip_event.proto │ │ ├── network_get_execution_time.proto │ │ ├── network_get_version_info.proto │ │ ├── network_service.proto │ │ ├── node_create.proto │ │ ├── node_delete.proto │ │ ├── node_stake_update.proto │ │ ├── node_update.proto │ │ ├── query.proto │ │ ├── query_header.proto │ │ ├── response.proto │ │ ├── response_code.proto │ │ ├── response_header.proto │ │ ├── schedulable_transaction_body.proto │ │ ├── schedule_create.proto │ │ ├── schedule_delete.proto │ │ ├── schedule_get_info.proto │ │ ├── schedule_service.proto │ │ ├── schedule_sign.proto │ │ ├── smart_contract_service.proto │ │ ├── state │ │ │ ├── addressbook │ │ │ │ └── node.proto │ │ │ ├── blockrecords │ │ │ │ ├── block_info.proto │ │ │ │ └── running_hashes.proto │ │ │ ├── blockstream │ │ │ │ └── block_stream_info.proto │ │ │ ├── common.proto │ │ │ ├── congestion │ │ │ │ └── congestion_level_starts.proto │ │ │ ├── consensus │ │ │ │ └── topic.proto │ │ │ ├── contract │ │ │ │ ├── bytecode.proto │ │ │ │ └── storage_slot.proto │ │ │ ├── entity │ │ │ │ └── entity_counts.proto │ │ │ ├── file │ │ │ │ └── file.proto │ │ │ ├── hints │ │ │ │ └── hints_types.proto │ │ │ ├── history │ │ │ │ └── history_types.proto │ │ │ ├── primitives.proto │ │ │ ├── recordcache │ │ │ │ └── recordcache.proto │ │ │ ├── roster │ │ │ │ ├── ledger_id.proto │ │ │ │ ├── roster.proto │ │ │ │ └── roster_state.proto │ │ │ ├── schedule │ │ │ │ └── schedule.proto │ │ │ ├── throttles │ │ │ │ └── throttle_usage_snapshots.proto │ │ │ ├── token │ │ │ │ ├── account.proto │ │ │ │ ├── account_pending_airdrop.proto │ │ │ │ ├── network_staking_rewards.proto │ │ │ │ ├── nft.proto │ │ │ │ ├── node_rewards.proto │ │ │ │ ├── staking_node_info.proto │ │ │ │ ├── token.proto │ │ │ │ └── token_relation.proto │ │ │ └── tss │ │ │ │ ├── tss_encryption_keys.proto │ │ │ │ ├── tss_message_map_key.proto │ │ │ │ └── tss_vote_map_key.proto │ │ ├── state_signature_transaction.proto │ │ ├── system_delete.proto │ │ ├── system_undelete.proto │ │ ├── throttle_definitions.proto │ │ ├── timestamp.proto │ │ ├── token_airdrop.proto │ │ ├── token_associate.proto │ │ ├── token_burn.proto │ │ ├── token_cancel_airdrop.proto │ │ ├── token_claim_airdrop.proto │ │ ├── token_create.proto │ │ ├── token_delete.proto │ │ ├── token_dissociate.proto │ │ ├── token_fee_schedule_update.proto │ │ ├── token_freeze_account.proto │ │ ├── token_get_account_nft_infos.proto │ │ ├── token_get_info.proto │ │ ├── token_get_nft_info.proto │ │ ├── token_get_nft_infos.proto │ │ ├── token_grant_kyc.proto │ │ ├── token_mint.proto │ │ ├── token_pause.proto │ │ ├── token_reject.proto │ │ ├── token_revoke_kyc.proto │ │ ├── token_service.proto │ │ ├── token_unfreeze_account.proto │ │ ├── token_unpause.proto │ │ ├── token_update.proto │ │ ├── token_update_nfts.proto │ │ ├── token_wipe_account.proto │ │ ├── transaction.proto │ │ ├── transaction_contents.proto │ │ ├── transaction_get_fast_record.proto │ │ ├── transaction_get_receipt.proto │ │ ├── transaction_get_record.proto │ │ ├── transaction_receipt.proto │ │ ├── transaction_record.proto │ │ ├── transaction_response.proto │ │ ├── unchecked_submit.proto │ │ ├── util_prng.proto │ │ └── util_service.proto │ │ └── streams │ │ ├── account_balance_file.proto │ │ ├── contract_action.proto │ │ ├── contract_bytecode.proto │ │ ├── contract_state_change.proto │ │ ├── hash_object.proto │ │ ├── record_stream_file.proto │ │ ├── sidecar_file.proto │ │ └── signature_file.proto │ ├── tsconfig.json │ └── vite.config.js ├── playwright.config.js ├── pnpm-lock.yaml ├── rollup.config.js ├── scripts ├── generate-request-and-status-files.js ├── helpers │ ├── request-type.js │ └── status-file.js └── update-address-books.js ├── src ├── BadEntityIdError.js ├── Cache.js ├── Duration.js ├── EntityIdHelper.js ├── EthereumFlow.js ├── EthereumTransaction.js ├── EthereumTransactionData.js ├── EthereumTransactionDataEip1559.js ├── EthereumTransactionDataEip2930.js ├── EthereumTransactionDataLegacy.js ├── EvmAddress.js ├── ExchangeRate.js ├── ExchangeRates.js ├── Executable.js ├── FeeComponents.js ├── FeeData.js ├── FeeDataType.js ├── FeeSchedule.js ├── FeeSchedules.js ├── FreezeType.js ├── Hbar.js ├── HbarUnit.js ├── Key.js ├── KeyList.js ├── LedgerId.js ├── LocalProvider.js ├── ManagedNode.js ├── ManagedNodeAddress.js ├── MaxAttemptsOrTimeoutError.js ├── MaxQueryPaymentExceeded.js ├── MirrorNode.js ├── Mnemonic.js ├── Node.js ├── ObjectMap.js ├── PrecheckStatusError.js ├── PrivateKey.js ├── PrngTransaction.js ├── Provider.js ├── PublicKey.js ├── ReceiptStatusError.js ├── RecordStatusError.js ├── RequestType.js ├── Signer.js ├── SignerSignature.js ├── StakingInfo.js ├── Status.js ├── StatusError.js ├── Timestamp.js ├── TransactionFeeSchedule.js ├── Transfer.js ├── Wallet.js ├── account │ ├── AccountAllowanceAdjustTransaction.js │ ├── AccountAllowanceApproveTransaction.js │ ├── AccountAllowanceDeleteTransaction.js │ ├── AccountBalance.js │ ├── AccountBalanceQuery.js │ ├── AccountCreateTransaction.js │ ├── AccountDeleteTransaction.js │ ├── AccountId.js │ ├── AccountInfo.js │ ├── AccountInfoFlow.js │ ├── AccountInfoQuery.js │ ├── AccountRecordsQuery.js │ ├── AccountUpdateTransaction.js │ ├── HbarAllowance.js │ ├── HbarTransferMap.js │ ├── LiveHash.js │ ├── LiveHashAddTransaction.js │ ├── LiveHashDeleteTransaction.js │ ├── LiveHashQuery.js │ ├── NullableTokenDecimalMap.js │ ├── ProxyStaker.js │ ├── TokenAllowance.js │ ├── TokenBalanceMap.js │ ├── TokenDecimalMap.js │ ├── TokenNftAllowance.js │ ├── TokenNftTransferMap.js │ ├── TokenRelationship.js │ ├── TokenRelationshipMap.js │ ├── TokenTransferAccountMap.js │ ├── TokenTransferMap.js │ └── TransferTransaction.js ├── address_book │ ├── AddressBooks.js │ ├── Endpoint.js │ ├── IPv4Address.js │ ├── IPv4AddressPart.js │ ├── NodeAddress.js │ └── NodeAddressBook.js ├── array.js ├── base32.js ├── browser.js ├── channel │ ├── Channel.js │ ├── MirrorChannel.js │ ├── NativeChannel.js │ ├── NodeChannel.js │ ├── NodeMirrorChannel.js │ └── WebChannel.js ├── client │ ├── Client.js │ ├── ManagedNetwork.js │ ├── MirrorNetwork.js │ ├── NativeClient.js │ ├── Network.js │ ├── NodeClient.js │ ├── WebClient.js │ └── addressbooks │ │ ├── mainnet.js │ │ ├── previewnet.js │ │ └── testnet.js ├── constants │ └── ClientConstants.js ├── contract │ ├── ContractByteCodeQuery.js │ ├── ContractCallQuery.js │ ├── ContractCreateFlow.js │ ├── ContractCreateTransaction.js │ ├── ContractDeleteTransaction.js │ ├── ContractExecuteTransaction.js │ ├── ContractFunctionParameters.js │ ├── ContractFunctionResult.js │ ├── ContractFunctionSelector.js │ ├── ContractId.js │ ├── ContractInfo.js │ ├── ContractInfoQuery.js │ ├── ContractLogInfo.js │ ├── ContractNonceInfo.js │ ├── ContractStateChange.js │ ├── ContractUpdateTransaction.js │ ├── DelegateContractId.js │ └── StorageChange.js ├── cryptography │ ├── keccak.js │ ├── sha384.browser.js │ ├── sha384.js │ └── sha384.native.js ├── encoding │ ├── base64.native.js │ ├── hex.browser.js │ ├── hex.js │ ├── hex.native.js │ ├── utf8.browser.js │ ├── utf8.js │ └── utf8.native.js ├── exports.js ├── file │ ├── FileAppendTransaction.js │ ├── FileContentsQuery.js │ ├── FileCreateTransaction.js │ ├── FileDeleteTransaction.js │ ├── FileId.js │ ├── FileInfo.js │ ├── FileInfoQuery.js │ └── FileUpdateTransaction.js ├── grpc │ ├── GrpcServiceError.js │ └── GrpcStatus.js ├── http │ ├── HttpError.js │ └── HttpStatus.js ├── index.js ├── logger │ ├── LogLevel.js │ └── Logger.js ├── long.js ├── native.js ├── network │ ├── AddressBookQuery.js │ ├── NetworkVersionInfo.js │ ├── NetworkVersionInfoQuery.js │ └── SemanticVersion.js ├── node │ ├── NodeCreateTransaction.js │ ├── NodeDeleteTransaction.js │ ├── NodeUpdateTransaction.js │ └── ServiceEndpoint.js ├── query │ ├── CostQuery.js │ ├── MirrorNodeContractCallQuery.js │ ├── MirrorNodeContractEstimateQuery.js │ ├── MirrorNodeContractQuery.js │ ├── Query.js │ └── QueryBase.js ├── schedule │ ├── ScheduleCreateTransaction.js │ ├── ScheduleDeleteTransaction.js │ ├── ScheduleId.js │ ├── ScheduleInfo.js │ ├── ScheduleInfoQuery.js │ └── ScheduleSignTransaction.js ├── system │ ├── FreezeTransaction.js │ ├── SystemDeleteTransaction.js │ └── SystemUndeleteTransaction.js ├── token │ ├── AbstractTokenTransferTransaction.js │ ├── AirdropPendingTransaction.js │ ├── AssessedCustomFee.js │ ├── CustomFee.js │ ├── CustomFixedFee.js │ ├── CustomFractionalFee.js │ ├── CustomRoyaltyFee.js │ ├── FeeAssessmentMethod.js │ ├── NftId.js │ ├── PendingAirdropId.js │ ├── PendingAirdropRecord.js │ ├── TokenAirdropTransaction.js │ ├── TokenAssociateTransaction.js │ ├── TokenAssociation.js │ ├── TokenBurnTransaction.js │ ├── TokenCancelAirdropTransaction.js │ ├── TokenClaimAirdropTransaction.js │ ├── TokenCreateTransaction.js │ ├── TokenDeleteTransaction.js │ ├── TokenDissociateTransaction.js │ ├── TokenFeeScheduleUpdateTransaction.js │ ├── TokenFreezeTransaction.js │ ├── TokenGrantKycTransaction.js │ ├── TokenId.js │ ├── TokenInfo.js │ ├── TokenInfoQuery.js │ ├── TokenKeyValidation.js │ ├── TokenMintTransaction.js │ ├── TokenNftInfo.js │ ├── TokenNftInfoQuery.js │ ├── TokenNftTransfer.js │ ├── TokenNftsUpdateTransaction.js │ ├── TokenPauseTransaction.js │ ├── TokenReference.js │ ├── TokenRejectFlow.js │ ├── TokenRejectTransaction.js │ ├── TokenRevokeKycTransaction.js │ ├── TokenSupplyType.js │ ├── TokenTransfer.js │ ├── TokenType.js │ ├── TokenUnfreezeTransaction.js │ ├── TokenUnpauseTransaction.js │ ├── TokenUpdateNftsTransaction.js │ ├── TokenUpdateTransaction.js │ └── TokenWipeTransaction.js ├── topic │ ├── SubscriptionHandle.js │ ├── TopicCreateTransaction.js │ ├── TopicDeleteTransaction.js │ ├── TopicId.js │ ├── TopicInfo.js │ ├── TopicInfoQuery.js │ ├── TopicMessage.js │ ├── TopicMessageChunk.js │ ├── TopicMessageQuery.js │ ├── TopicMessageSubmitTransaction.js │ └── TopicUpdateTransaction.js ├── transaction │ ├── BatchTransaction.js │ ├── CustomFeeLimit.js │ ├── List.js │ ├── NodeAccountIdSignatureMap.js │ ├── NodeAccountIdSignatureMapLegacy.js │ ├── SignableNodeTransactionBodyBytes.js │ ├── SignatureMap.js │ ├── SignatureMapLegacy.js │ ├── SignaturePairMap.js │ ├── TokenTransfer.js │ ├── Transaction.js │ ├── TransactionHashMap.js │ ├── TransactionId.js │ ├── TransactionReceipt.js │ ├── TransactionReceiptQuery.js │ ├── TransactionRecord.js │ ├── TransactionRecordQuery.js │ └── TransactionResponse.js ├── types.d.ts ├── util.js ├── util │ └── ASN1-Decoder.js └── version.js ├── tck ├── .dockerignore ├── Dockerfile ├── README.md ├── Taskfile.yml ├── docker-compose.yml ├── mapping.ts ├── methods │ ├── account.ts │ ├── index.ts │ ├── key.ts │ ├── sdk.ts │ └── token.ts ├── package-lock.json ├── package.json ├── params │ ├── account.ts │ ├── allowance.ts │ ├── common-tx-params.ts │ ├── key.ts │ ├── sdk.ts │ ├── token.ts │ └── transfer.ts ├── response │ ├── account.ts │ ├── asn1-decode.ts │ ├── json-rpc-error.ts │ ├── key.ts │ ├── sdk.ts │ └── token.ts ├── sdk_data.ts ├── server.ts ├── tsconfig.json └── utils │ ├── asn1-decoder.ts │ ├── constants │ ├── config.ts │ └── properties.ts │ ├── custom-error.ts │ ├── enums │ └── account-key.ts │ ├── helpers │ ├── account.ts │ └── token.ts │ ├── invalid-param-error.ts │ └── key.ts ├── test ├── .eslintrc.cjs ├── integration │ ├── AccountBalanceIntegrationTest.js │ ├── AccountCreateIntegrationTest.js │ ├── AccountDeleteIntegrationTest.js │ ├── AccountIdTest.js │ ├── AccountInfoIntegrationTest.js │ ├── AccountRecordsIntegrationTest.js │ ├── AccountUpdateIntegrationTest.js │ ├── AddressBookQueryTest.js │ ├── BatchTransactionIntegrationTest.js │ ├── ClientConstantsIntegrationTest.js │ ├── ClientIntegrationTest.js │ ├── ContractBytecodeIntegrationTest.js │ ├── ContractCallIntegrationTest.js │ ├── ContractCreateFlowIntegrationTest.js │ ├── ContractCreateIntegrationTest.js │ ├── ContractDeleteIntegrationTest.js │ ├── ContractExecuteIntegrationTest.js │ ├── ContractFunctionParametersIntegrationTest.js │ ├── ContractInfoIntegrationTest.js │ ├── ContractUpdateIntegrationTest.js │ ├── CryptoTransferIntergationTest.js │ ├── CustomFeesIntegrationTest.js │ ├── EthereumTransactionIntegrationTest.js │ ├── FileAppendIntegrationTest.js │ ├── FileContentsIntegrationTest.js │ ├── FileCreateIntegrationTest.js │ ├── FileDeleteIntegrationTest.js │ ├── FileInfoIntegrationTest.js │ ├── FileUpdateIntegrationTest.js │ ├── FreezeTransactionIntegrationTest.js │ ├── GetCostIntegrationTest.js │ ├── GrpcMetadataIntegrationTest.js │ ├── LegacyTransactionIntegrationTest.js │ ├── LiveHashIntegrationTest.js │ ├── LocalWalletTest.js │ ├── MirrorNodeContractEstimateQuery.js │ ├── MirrorNodeContractQuery.js │ ├── NetworkVersionInfoIntegrationTest.js │ ├── NftAllowancesIntegrationTest.js │ ├── NodeCreateTransactionIntegrationTest.js │ ├── PrivateKey.js │ ├── QueryIntegrationTest.js │ ├── ScheduleCreateIntegrationTest.js │ ├── SystemIntegrationTest.js │ ├── TokenAirdropIntegrationTest.js │ ├── TokenAllowancesIntegrationTest.js │ ├── TokenAssociateIntegrationTest.js │ ├── TokenBurnIntegrationTest.js │ ├── TokenCancelAirdropTransaction.js │ ├── TokenClaimAirdropTransaction.js │ ├── TokenCreateIntegrationTest.js │ ├── TokenDeleteIntegrationTest.js │ ├── TokenDissociateIntegrationTest.js │ ├── TokenFreezeIntegrationTest.js │ ├── TokenGrantKycIntegrationTest.js │ ├── TokenInfoIntegrationTest.js │ ├── TokenMintIntegrationTest.js │ ├── TokenNftIntegrationTest.js │ ├── TokenNftsUpdateTransactionIntegrationTest.js │ ├── TokenRejectFlowIntegrationTest.js │ ├── TokenRejectIntegrationTest.js │ ├── TokenRevokeKycIntegrationTest.js │ ├── TokenTransferIntegrationTest.js │ ├── TokenUnfreezeIntegrationTest.js │ ├── TokenUpdateIntegrationTest.js │ ├── TokenWipeIntegrationTest.js │ ├── TopicCreateIntegrationTest.js │ ├── TopicDeleteIntegrationTest.js │ ├── TopicInfoIntegrationTest.js │ ├── TopicMessageIntegrationTest.js │ ├── TopicMessageQueryTest.js │ ├── TopicUpdateIntegrationTest.js │ ├── TransactionIntegrationTest.js │ ├── TransactionReceiptIntegrationTest.js │ ├── TransactionRecordIntegrationTest.js │ ├── TransactionResponseTest.js │ ├── WalletIntegrationTest.js │ ├── client │ │ ├── BaseIntegrationTestEnv.js │ │ ├── NodeIntegrationTestEnv.js │ │ ├── TestnetIntegrationTestEnv.js │ │ └── WebIntegrationTestEnv.js │ ├── contents.js │ ├── resources │ │ └── ReadData.sol │ └── utils │ │ └── Fixtures.js ├── tsconfig.json ├── unit │ ├── AccountAllowanceApproveTransaction.js │ ├── AccountAllowanceDeleteTransaction.js │ ├── AccountCreateTransaction.js │ ├── AccountDeleteTransaction.js │ ├── AccountInfo.js │ ├── AccountInfoQuery.js │ ├── AccountUpdateTransaction.js │ ├── AirdropCancelTransaction.js │ ├── AirdropClaimTransaction.js │ ├── BatchTransaction.js │ ├── ChecksumValidation.js │ ├── ContractDeleteTransaction.js │ ├── ContractExecuteTransaction.js │ ├── ContractFunctionParameters.js │ ├── ContractFunctionResult.js │ ├── ContractId.js │ ├── ContractNonceInfo.js │ ├── ContractUpdateTransaction.js │ ├── CustomFeeLimit.js │ ├── CustomFractionalFee.js │ ├── DelegateContractId.js │ ├── EcdsaPrivateKey.js │ ├── Ed25519PrivateKey.js │ ├── EntityIdHelper.js │ ├── EthereumTransaction.js │ ├── EthereumTransactionData.js │ ├── ExchangeRate.js │ ├── Executable.js │ ├── FeeComponents.js │ ├── FeeData.js │ ├── FeeDataType.js │ ├── FileUpdateTransaction.js │ ├── FreezeTransaction.js │ ├── Hbar.js │ ├── HbarAllowance.js │ ├── LedgerId.js │ ├── ManagedNodeAddress.js │ ├── MirrorNodeContractCallQuery.js │ ├── MirrorNodeContractEstimateQuery.js │ ├── MirrorNodeContractQuery.js │ ├── Mnemonic.js │ ├── Mocker.js │ ├── NativeChannelUserAgent.js │ ├── NativeClient.js │ ├── NodeDeleteTransaction.js │ ├── PendingAirdropId.js │ ├── PrivateKey.js │ ├── PrivateKeyLegacy.js │ ├── PrngTransaction.js │ ├── PublicKey.js │ ├── PublicKeyLegacy.js │ ├── RequestType.js │ ├── ScheduleInfo.js │ ├── Serialize.js │ ├── Status.js │ ├── Timestamp.js │ ├── TokenAirdropTransaction.js │ ├── TokenAllowance.js │ ├── TokenAssociateTransaction.js │ ├── TokenCreateTransaction.js │ ├── TokenFreezeTransaction.js │ ├── TokenGrantKycTransaction.js │ ├── TokenInfo.js │ ├── TokenNftAllowance.js │ ├── TokenNftInfoQuery.js │ ├── TokenPauseTransaction.js │ ├── TokenRejectTransaction.js │ ├── TokenTransfer.js │ ├── TokenUnfreezeTransaction.js │ ├── TokenUnpauseTransaction.js │ ├── TokenUpdateNftsTransaction.js │ ├── TokenUpdateTransaction.js │ ├── TopicCreateTransaction.js │ ├── TopicInfo.js │ ├── TopicMessageSubmitTransaction.js │ ├── TopicUpdateTransaction.js │ ├── Transaction.js │ ├── TransactionId.js │ ├── TransactionLegacy.js │ ├── TransactionReceipt.js │ ├── TransactionRecord.js │ ├── TransactionResponse.js │ ├── TransferTransaction.js │ ├── WebChannelUserAgent.js │ ├── hex.js │ ├── keccak256.js │ ├── node │ │ ├── AccountId.js │ │ ├── AccountInfoMocking.js │ │ ├── ContractCreateFlowMocking.js │ │ ├── EthereumFlowMocking.js │ │ ├── FileAppendMocking.js │ │ ├── FileAppendTransaction.js │ │ ├── LoggerTest.js │ │ ├── MaxAttemptsOrTimeoutError.js │ │ ├── NodeClient.js │ │ ├── NodeCreateTransaction.js │ │ ├── NodeUpdateTransaction.js │ │ ├── TokenRejectFlow.js │ │ ├── TopicMessageMocking.js │ │ └── TransactionReceiptMocking.js │ └── util.js ├── vitest-browser.config.ts ├── vitest-node-integration.config.ts └── vitest-node.config.ts ├── tsconfig.json ├── typedoc.json └── update_protos.sh /.babelrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@babel/plugin-transform-modules-commonjs", 4 | "@babel/plugin-syntax-dynamic-import", 5 | "@babel/plugin-proposal-export-namespace-from", 6 | [ 7 | "babel-plugin-dynamic-import-node", 8 | { 9 | "noInterop": true 10 | } 11 | ], 12 | [ 13 | "module-rewrite", 14 | { "replaceFunc": "./build/replace-module-paths.cjs" } 15 | ] 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | root = true 3 | 4 | [*] 5 | end_of_line = lf 6 | insert_final_newline = true 7 | charset = utf-8 8 | indent_style = space 9 | indent_size = 4 10 | trim_trailing_whitespace = true 11 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | # The operator is responsible for paying transaction and query fees 2 | # 3 | # The `LocalWallet` uses the environment variables `OPERATOR_ID`, `OPERATOR_KEY`, 4 | # and `HEDERA_NETWORK` 5 | 6 | # Hedera Operator Account ID 7 | OPERATOR_ID="0.0.2336" 8 | 9 | # Hedera Operator Private Key 10 | OPERATOR_KEY="302e020100300506032b6570042204202cc589a6343ff8d05b71edf54f69bff4cd8faeec9b04d16f55d1d78fe23841af" 11 | 12 | # Hedera Network 13 | # Options: 14 | # - previewnet: Connects to the Hedera preview network. 15 | # - local-node: Connects to a local Hedera node for development/testing. 16 | HEDERA_NETWORK="previewnet" 17 | -------------------------------------------------------------------------------- /.github/codecov.yaml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | target: 90% 6 | threshold: 1% 7 | ignore: 8 | - "src/token/TokenNftsUpdateTransaction.js" 9 | - "src/account/AccountAllowanceAdjustTransaction.js" 10 | - "src/account/LiveHashAddTransaction.js" 11 | - "src/account/LiveHashDeleteTransaction.js" 12 | - "src/account/LiveHashQuery.js" 13 | - "src/system/SystemUndeleteTransaction.js" 14 | - "src/system/SystemDeleteTransaction.js" 15 | - "src/contract/StorageChange.js" 16 | - "src/contract/ContractStateChange.js" 17 | - "src/transaction/SignatureMapLegacy.js" 18 | - "src/transaction/NodeAccountIdSignatureMapLegacy.js" 19 | -------------------------------------------------------------------------------- /.github/workflows/pr_check.yml: -------------------------------------------------------------------------------- 1 | name: 'PR Formatting' 2 | on: 3 | workflow_dispatch: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - reopened 8 | - edited 9 | - synchronize 10 | 11 | defaults: 12 | run: 13 | shell: bash 14 | 15 | permissions: 16 | contents: read 17 | 18 | concurrency: 19 | group: pr-checks-${{ github.workflow }}-${{ github.head_ref || github.run_id }} 20 | cancel-in-progress: true 21 | 22 | jobs: 23 | title-check: 24 | name: Title Check 25 | runs-on: hiero-client-sdk-linux-medium 26 | if: ${{ !github.event.pull_request.base.repo.fork }} 27 | permissions: 28 | statuses: write 29 | steps: 30 | - name: Harden Runner 31 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 32 | with: 33 | egress-policy: audit 34 | 35 | - name: Check PR Title 36 | uses: step-security/conventional-pr-title-action@8a8989588c2547f23167c4c42f0fb2356479e81b # v3.2.1 37 | env: 38 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 39 | -------------------------------------------------------------------------------- /.github/workflows/renovate.yml: -------------------------------------------------------------------------------- 1 | name: Renovate 2 | on: 3 | schedule: 4 | # The "*" (#42, asterisk) character has special semantics in YAML, so this 5 | # string has to be quoted. 6 | - cron: '0 0 * * 0' 7 | workflow_dispatch: 8 | 9 | defaults: 10 | run: 11 | shell: bash 12 | 13 | permissions: 14 | contents: read 15 | 16 | jobs: 17 | renovate: 18 | runs-on: hiero-client-sdk-linux-medium 19 | steps: 20 | - name: Harden Runner 21 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 22 | with: 23 | egress-policy: audit 24 | 25 | - name: Checkout Code 26 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 27 | with: 28 | submodules: recursive 29 | 30 | - name: Self-hosted Renovate 31 | uses: renovatebot/github-action@8058cfe11252651a837a58e2e3370fbc0e72c658 # v42.0.4 32 | with: 33 | configurationFile: .github/renovate.json 34 | token: ${{ secrets.RENOVATE_TOKEN }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # editor files 2 | .idea/ 3 | 4 | # npm dependencies 5 | node_modules/ 6 | 7 | # built files 8 | # we currently run babel over the JavaScript before shipping 9 | # this enables us to easily support older versions of Node 10 | lib/ 11 | dist/ 12 | test/lib/ 13 | **/test-results/ 14 | 15 | # generated documentation 16 | docs/ 17 | 18 | # local environment (for examples) 19 | .env 20 | 21 | # instabul (code coverage) 22 | .nyc_output/ 23 | .coverage/ 24 | coverage/ 25 | 26 | .yalc 27 | yalc.lock 28 | 29 | examples/address-book.proto.bin 30 | 31 | #ds store 32 | .DS_Store -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "packages/proto/src/services"] 2 | path = packages/proto/src/services 3 | url = https://github.com/hiero-ledger/hiero-consensus-node.git -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | strict-peer-dependencies=false 2 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@istanbuljs/nyc-config-babel", 3 | "all": true, 4 | "include": ["src/**/*.js"], 5 | "extension": [".js"] 6 | } 7 | -------------------------------------------------------------------------------- /build/replace-module-paths.cjs: -------------------------------------------------------------------------------- 1 | // ensure that all local imports go from .js to .cjs when moved to lib/ 2 | // https://github.com/liady/babel-plugin-module-rewrite 3 | module.exports = function replaceImport(originalPath, callingFileName, options) { 4 | let path = originalPath; 5 | 6 | if (global.process != null && global.process.env != null && global.process.env.HEDERA_SDK_TEST != null) { 7 | if ( 8 | originalPath.startsWith(".") && 9 | originalPath.endsWith(".js") && 10 | !callingFileName.includes("/test/") && 11 | path.includes("/src/") 12 | ) { 13 | path = path.replace(".js", ".cjs"); 14 | path = path.replace("src/", "lib/"); 15 | } 16 | } else { 17 | if (path.startsWith(".") && path.endsWith(".js")) { 18 | path = path.replace(".js", ".cjs"); 19 | } 20 | } 21 | 22 | return path; 23 | } 24 | -------------------------------------------------------------------------------- /check_yalc_dep.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | grep "\"${1}\": \"file:.yalc/${1}\"" package.json > /dev/null 4 | if [[ $? -eq 0 ]]; then 5 | test -d .yalc/${1} 6 | fi 7 | -------------------------------------------------------------------------------- /common_js_test/Taskfile.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | silent: true 4 | 5 | tasks: 6 | default: 7 | deps: 8 | - build 9 | 10 | install: 11 | cmds: 12 | - pnpm i 13 | 14 | build: 15 | deps: 16 | - install 17 | 18 | clean: 19 | cmds: 20 | - rm -rf node_modules 21 | 22 | test: 23 | deps: 24 | - install 25 | cmds: 26 | - ./node_modules/.bin/mocha --exit --inline-diffs -r @babel/register -r chai/register-expect.js "src/test.js" --timeout 120000 27 | -------------------------------------------------------------------------------- /common_js_test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "integration_tests", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha -r @babel/register -r chai/register-expect.js 'src/test.js'" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "@hashgraph/sdk": "link:..", 13 | "chai": "^4.3.6", 14 | "mocha": "~10.6.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /common_js_test/src/test.js: -------------------------------------------------------------------------------- 1 | const { Client, AccountBalanceQuery } = require("@hashgraph/sdk"); 2 | 3 | describe("CommonJS", function () { 4 | it("should query each node's balance", async function () { 5 | const client = Client.forTestnet(); 6 | 7 | let succeededAtLeastOnce = false; 8 | 9 | // Iterate over the nodes in the network 10 | for (const [, nodeAccountId] of Object.entries(client.network)) { 11 | try { 12 | await new AccountBalanceQuery() 13 | .setNodeAccountIds([nodeAccountId]) 14 | .setAccountId(nodeAccountId) 15 | .execute(client); 16 | succeededAtLeastOnce = true; 17 | } catch (error) { 18 | console.log(`Failed for ${nodeAccountId}`); 19 | } 20 | } 21 | 22 | // Close the client connection 23 | client.close(); 24 | 25 | // Ensure that at least one attempt was successful 26 | if (!succeededAtLeastOnce) { 27 | throw new Error("No successful query attempts were made."); 28 | } 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /examples/.env: -------------------------------------------------------------------------------- 1 | # Local Node 2 | OPERATOR_KEY=0xa608e2130a0a3cb34f86e757303c862bee353d9ab77ba4387ec084f881d420d4 3 | OPERATOR_ID=0.0.1022 4 | HEDERA_NETWORK=local-node 5 | 6 | TREASURY_ID=0.0.1023 7 | TREASURY_KEY=0xbbd0894de0b4ecfa862e963825c5448d2d17f807a16869526bff29185747acdb 8 | ALICE_ID=0.0.1024 9 | ALICE_KEY=0x8fd50f886a2e7ed499e7686efd1436b50aa9b64b26e4ecc4e58ca26e6257b67d 10 | BOB_ID=0.0.1025 11 | BOB_KEY=0x62c966ebd9dcc0fc16a553b2ef5b72d1dca05cdf5a181027e761171e9e947420 12 | NODE_COMMAND=node -------------------------------------------------------------------------------- /examples/.env.example: -------------------------------------------------------------------------------- 1 | # Variable used in script that runs all examples 2 | NODE_COMMAND=node -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | !.env 2 | -------------------------------------------------------------------------------- /examples/Taskfile.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | silent: true 4 | 5 | tasks: 6 | default: 7 | deps: 8 | - build 9 | 10 | install: 11 | cmds: 12 | - pnpm i 13 | 14 | run-examples: 15 | description: Run JavaScript examples in the "examples" folder 16 | cmds: 17 | - node run-all-examples.js 18 | build: 19 | cmds: 20 | - task: install 21 | - task: format 22 | - task: lint 23 | 24 | clean: 25 | cmds: 26 | - rm -rf node_modules 27 | 28 | format: 29 | cmds: 30 | - ./node_modules/.bin/prettier "*.json" "*.js" --write > /dev/null 31 | 32 | lint: 33 | deps: 34 | - "lint:types" 35 | - "lint:dpdm" 36 | - "lint:format" 37 | - "lint:js" 38 | 39 | "lint:types": 40 | cmds: 41 | - ./node_modules/.bin/tsc 42 | 43 | "lint:dpdm": 44 | cmds: 45 | - ./node_modules/.bin/dpdm src/index.js --circular true --tree false --warning false > /dev/null 46 | 47 | "lint:format": 48 | cmds: 49 | - ./node_modules/.bin/prettier "*.json" "*.js" --check > /dev/null 50 | 51 | "lint:js": 52 | cmds: 53 | - ./node_modules/.bin/eslint --fix "*.json" "*.js" 54 | -------------------------------------------------------------------------------- /examples/create-account.js: -------------------------------------------------------------------------------- 1 | import { 2 | Wallet, 3 | LocalProvider, 4 | PrivateKey, 5 | AccountCreateTransaction, 6 | Hbar, 7 | } from "@hashgraph/sdk"; 8 | 9 | import dotenv from "dotenv"; 10 | 11 | dotenv.config(); 12 | 13 | async function main() { 14 | if ( 15 | process.env.OPERATOR_ID == null || 16 | process.env.OPERATOR_KEY == null || 17 | process.env.HEDERA_NETWORK == null 18 | ) { 19 | throw new Error( 20 | "Environment variables OPERATOR_ID, HEDERA_NETWORK, and OPERATOR_KEY are required.", 21 | ); 22 | } 23 | 24 | const provider = new LocalProvider(); 25 | 26 | const wallet = new Wallet( 27 | process.env.OPERATOR_ID, 28 | process.env.OPERATOR_KEY, 29 | provider, 30 | ); 31 | 32 | const newKey = PrivateKey.generate(); 33 | 34 | console.log(`private key = ${newKey.toString()}`); 35 | console.log(`public key = ${newKey.publicKey.toString()}`); 36 | 37 | try { 38 | let transaction = await new AccountCreateTransaction() 39 | .setInitialBalance(new Hbar(10)) // 10 h 40 | .setKeyWithoutAlias(newKey.publicKey) 41 | .freezeWithSigner(wallet); 42 | 43 | transaction = await transaction.signWithSigner(wallet); 44 | 45 | const response = await transaction.executeWithSigner(wallet); 46 | 47 | const receipt = await response.getReceiptWithSigner(wallet); 48 | 49 | console.log(`account id = ${receipt.accountId.toString()}`); 50 | } catch (error) { 51 | console.error(error); 52 | } 53 | 54 | provider.close(); 55 | } 56 | 57 | void main(); 58 | -------------------------------------------------------------------------------- /examples/custom-grpc-web-proxies-network/.env.sample: -------------------------------------------------------------------------------- 1 | # Hedera Operator Account ID 2 | REACT_APP_OPERATOR_ID="YOUR_OPERATOR_ID" 3 | 4 | # Hedera Operator Private Key 5 | REACT_APP_OPERATOR_KEY="YOUR_PRIVATE_KEY" 6 | 7 | -------------------------------------------------------------------------------- /examples/custom-grpc-web-proxies-network/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # production 7 | /build 8 | 9 | .env 10 | 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | -------------------------------------------------------------------------------- /examples/custom-grpc-web-proxies-network/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-grpc-network", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@hashgraph/sdk": "link:../..", 7 | "@testing-library/jest-dom": "^5.17.0", 8 | "@testing-library/react": "^13.4.0", 9 | "@testing-library/user-event": "^13.5.0", 10 | "react": "^18.3.1", 11 | "react-dom": "^18.3.1", 12 | "react-scripts": "5.0.1", 13 | "web-vitals": "^2.1.4" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": [ 23 | "react-app", 24 | "react-app/jest" 25 | ] 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.2%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/custom-grpc-web-proxies-network/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 23 | React App 24 | 25 | 26 | 27 |
28 | 38 | 39 | -------------------------------------------------------------------------------- /examples/custom-grpc-web-proxies-network/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", 4 | "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", 5 | "Helvetica Neue", sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | 15 | .App { 16 | text-align: center; 17 | } 18 | -------------------------------------------------------------------------------- /examples/custom-grpc-web-proxies-network/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | 6 | const root = ReactDOM.createRoot(document.getElementById("root")); 7 | root.render(); 8 | -------------------------------------------------------------------------------- /examples/demo-umd/bouncing-circles.svg: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /examples/demo-umd/builder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-sdk-js/09d2a937c4ed820b04468cd85a015739020cd33a/examples/demo-umd/builder.png -------------------------------------------------------------------------------- /examples/ecrecover_caller.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | pragma solidity >=0.5.0 <0.9.0; 3 | 4 | contract EcrecoverCaller { 5 | event EcrecoverResult(bytes result); 6 | address accountZeroZeroOne = address(0x0000000000000000000000000000000000000001); 7 | 8 | function callEcrecover(bytes32 messageHash, uint8 v, bytes32 r, bytes32 s) external pure returns (address) { 9 | address result = ecrecover(messageHash, v, r, s); 10 | return result; 11 | } 12 | 13 | function call0x1(bytes calldata callData) external payable returns (bool) { 14 | address target = accountZeroZeroOne; 15 | (bool success, bytes memory result) = target.call{value: msg.value}(callData); 16 | if (!success) { 17 | revert(); 18 | } 19 | emit EcrecoverResult(result); 20 | return success; 21 | } 22 | 23 | function send0x1() external payable { 24 | address payable target = payable(accountZeroZeroOne); 25 | target.transfer(msg.value); 26 | } 27 | 28 | function transfer0x1() external payable { 29 | address payable target = payable(accountZeroZeroOne); 30 | target.transfer(msg.value); 31 | } 32 | } -------------------------------------------------------------------------------- /examples/generate-key.js: -------------------------------------------------------------------------------- 1 | import { Mnemonic } from "@hashgraph/sdk"; 2 | 3 | async function main() { 4 | try { 5 | // generate a 24-word mnemonic 6 | const mnemonic = await Mnemonic.generate(); 7 | console.log(`24 words mnemonic = ${mnemonic.toString()}`); 8 | 9 | const key = await mnemonic.toStandardEd25519PrivateKey("", 0); 10 | console.log(`private key = ${key.toString()}`); 11 | console.log(`public key = ${key.publicKey.toString()}`); 12 | 13 | // [...] 14 | 15 | // recover your key from the mnemonic 16 | // this takes space-separated or comma-separated words 17 | const recoveredMnemonic = await Mnemonic.fromString( 18 | mnemonic.toString(), 19 | ); 20 | const recoveredRootKey = 21 | await recoveredMnemonic.toStandardEd25519PrivateKey("", 0); 22 | 23 | recoveredRootKey.toString() === key.toString() 24 | ? console.log(`successful key recovery!`) 25 | : console.log(`key recovery failed!`); 26 | 27 | const mnemonic12 = await Mnemonic.generate12(); 28 | console.log(`12 words mnemonic = ${mnemonic12.toString()}`); 29 | 30 | const key12 = await mnemonic12.toStandardEd25519PrivateKey("", 0); 31 | console.log(`private key = ${key12.toString()}`); 32 | console.log(`public key = ${key12.publicKey.toString()}`); 33 | } catch (error) { 34 | console.error(error); 35 | } 36 | } 37 | 38 | void main() 39 | .then(() => process.exit(0)) 40 | .catch(() => process.exit(1)); 41 | -------------------------------------------------------------------------------- /examples/get-account-balance.js: -------------------------------------------------------------------------------- 1 | import { Wallet, LocalProvider, AccountBalanceQuery } from "@hashgraph/sdk"; 2 | 3 | import dotenv from "dotenv"; 4 | 5 | dotenv.config(); 6 | 7 | async function main() { 8 | if ( 9 | process.env.OPERATOR_ID == null || 10 | process.env.OPERATOR_KEY == null || 11 | process.env.HEDERA_NETWORK == null 12 | ) { 13 | throw new Error( 14 | "Environment variables OPERATOR_ID, HEDERA_NETWORK, and OPERATOR_KEY are required.", 15 | ); 16 | } 17 | 18 | const provider = new LocalProvider(); 19 | 20 | const wallet = new Wallet( 21 | process.env.OPERATOR_ID, 22 | process.env.OPERATOR_KEY, 23 | provider, 24 | ); 25 | 26 | try { 27 | const balance = await new AccountBalanceQuery() 28 | .setAccountId(wallet.getAccountId()) 29 | .executeWithSigner(wallet); 30 | 31 | console.log( 32 | `${wallet 33 | .getAccountId() 34 | .toString()} balance = ${balance.hbars.toString()}`, 35 | ); 36 | } catch (error) { 37 | console.error(Error); 38 | } 39 | 40 | provider.close(); 41 | } 42 | 43 | void main(); 44 | -------------------------------------------------------------------------------- /examples/get-account-info.js: -------------------------------------------------------------------------------- 1 | import { Wallet, LocalProvider, AccountInfoQuery, Hbar } from "@hashgraph/sdk"; 2 | 3 | import dotenv from "dotenv"; 4 | 5 | dotenv.config(); 6 | 7 | async function main() { 8 | if ( 9 | process.env.OPERATOR_ID == null || 10 | process.env.OPERATOR_KEY == null || 11 | process.env.HEDERA_NETWORK == null 12 | ) { 13 | throw new Error( 14 | "Environment variables OPERATOR_ID, HEDERA_NETWORK, and OPERATOR_KEY are required.", 15 | ); 16 | } 17 | 18 | const provider = new LocalProvider(); 19 | 20 | const wallet = new Wallet( 21 | process.env.OPERATOR_ID, 22 | process.env.OPERATOR_KEY, 23 | provider, 24 | ); 25 | 26 | try { 27 | const info = await new AccountInfoQuery() 28 | .setAccountId(wallet.getAccountId()) 29 | .setQueryPayment(new Hbar(1)) 30 | .executeWithSigner(wallet); 31 | 32 | console.log( 33 | `info.key = ${info.key.toString()}`, 34 | ); 35 | 36 | console.log( 37 | `info.isReceiverSignatureRequired =`, 38 | info.isReceiverSignatureRequired, 39 | ); 40 | 41 | console.log( 42 | `info.expirationTime = ${info.expirationTime 43 | .toDate() 44 | .toString()}`, 45 | ); 46 | } catch (error) { 47 | console.error(error); 48 | } 49 | 50 | provider.close(); 51 | } 52 | 53 | void main(); 54 | -------------------------------------------------------------------------------- /examples/get-address-book.js: -------------------------------------------------------------------------------- 1 | import { Client, FileId, AddressBookQuery } from "@hashgraph/sdk"; 2 | 3 | import fs from "node:fs/promises"; 4 | 5 | import dotenv from "dotenv"; 6 | 7 | dotenv.config(); 8 | 9 | async function main() { 10 | if (process.env.HEDERA_NETWORK == null) { 11 | throw new Error("Environment variable HEDERA_NETWORK is required."); 12 | } 13 | 14 | const client = Client.forName(process.env.HEDERA_NETWORK); 15 | 16 | if (process.env.HEDERA_NETWORK.toLowerCase() === "mainnet") { 17 | client 18 | .setMirrorNetwork(["mainnet-public.mirrornode.hedera.com:443"]) 19 | .setTransportSecurity(true); 20 | } 21 | 22 | const addressBook = await new AddressBookQuery() 23 | .setFileId(FileId.ADDRESS_BOOK) 24 | .execute(client); 25 | 26 | console.log(JSON.stringify(addressBook.toJSON(), null, 2)); 27 | 28 | await fs.writeFile("address-book.proto.bin", addressBook.toBytes()); 29 | 30 | client.close(); 31 | } 32 | 33 | void main(); 34 | -------------------------------------------------------------------------------- /examples/hello_world.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.22 <0.6.0; 2 | 3 | contract HelloWorld { 4 | // the contract's owner, set in the constructor 5 | address owner; 6 | 7 | constructor() public { 8 | // set the owner of the contract for `kill()` 9 | owner = msg.sender; 10 | } 11 | 12 | // return a string 13 | function greet() public pure returns (string memory) { 14 | return "Hello, world!"; 15 | } 16 | 17 | // recover the funds of the contract 18 | function kill() public { if (msg.sender == owner) selfdestruct(msg.sender); } 19 | } 20 | -------------------------------------------------------------------------------- /examples/legacy-way-sign-transaction.js: -------------------------------------------------------------------------------- 1 | import { 2 | PrivateKey, 3 | Client, 4 | AccountId, 5 | AccountCreateTransaction, 6 | } from "@hashgraph/sdk"; 7 | 8 | import dotenv from "dotenv"; 9 | 10 | dotenv.config(); 11 | 12 | const OPERATOR_ID = AccountId.fromString(process.env.OPERATOR_ID); 13 | const OPERATOR_KEY = PrivateKey.fromStringED25519(process.env.OPERATOR_KEY); 14 | const HEDERA_NETWORK = process.env.HEDERA_NETWORK; 15 | 16 | async function main() { 17 | // Step 0: Create and configure the SDK Client. 18 | const client = Client.forName(HEDERA_NETWORK); 19 | client.setOperator(OPERATOR_ID, OPERATOR_KEY); 20 | 21 | // Step 1: Generate private key for a future account create transaction 22 | const key = PrivateKey.generateED25519(); 23 | 24 | // Step 2: Create transaction without signing it 25 | const tx = new AccountCreateTransaction() 26 | .setKeyWithoutAlias(key.publicKey) 27 | .freezeWith(client); 28 | 29 | // Step 3: Sign transaction using your private key 30 | // eslint-disable-next-line deprecation/deprecation 31 | const signature = key.signTransaction(tx, true); 32 | 33 | // Step 4: add the generated signature to transaction 34 | // it will use the old legacy way because of the type of signature 35 | // eslint-disable-next-line deprecation/deprecation 36 | tx.addSignature(key.publicKey, signature); 37 | 38 | // Step 5: get the outcome of the transaction 39 | const { status } = await (await tx.execute(client)).getReceipt(client); 40 | console.log("STATUS OF TRANSACTION IS", status.toString()); 41 | 42 | client.close(); 43 | } 44 | 45 | void main(); 46 | -------------------------------------------------------------------------------- /examples/local-wallet-info-query.js: -------------------------------------------------------------------------------- 1 | import { Wallet, LocalProvider } from "@hashgraph/sdk"; 2 | 3 | import dotenv from "dotenv"; 4 | 5 | dotenv.config(); 6 | 7 | async function main() { 8 | if ( 9 | process.env.OPERATOR_ID == null || 10 | process.env.OPERATOR_KEY == null || 11 | process.env.HEDERA_NETWORK == null 12 | ) { 13 | throw new Error( 14 | "Environment variables OPERATOR_ID, HEDERA_NETWORK, and OPERATOR_KEY are required.", 15 | ); 16 | } 17 | 18 | const provider = new LocalProvider(); 19 | 20 | const wallet = new Wallet( 21 | process.env.OPERATOR_ID, 22 | process.env.OPERATOR_KEY, 23 | provider, 24 | ); 25 | 26 | try { 27 | const info = await wallet.getAccountInfo(); 28 | 29 | console.log( 30 | `info.key = ${info.key.toString()}`, 31 | ); 32 | 33 | console.log( 34 | `info.isReceiverSignatureRequired =`, 35 | info.isReceiverSignatureRequired, 36 | ); 37 | 38 | console.log( 39 | `info.expirationTime = ${info.expirationTime 40 | .toDate() 41 | .toString()}`, 42 | ); 43 | } catch (error) { 44 | console.error(error); 45 | } 46 | 47 | provider.close(); 48 | } 49 | 50 | void main(); 51 | -------------------------------------------------------------------------------- /examples/local-wallet-sign-transaction.js: -------------------------------------------------------------------------------- 1 | import { Wallet, LocalProvider, TransferTransaction } from "@hashgraph/sdk"; 2 | 3 | import dotenv from "dotenv"; 4 | 5 | dotenv.config(); 6 | 7 | async function main() { 8 | if ( 9 | process.env.OPERATOR_ID == null || 10 | process.env.OPERATOR_KEY == null || 11 | process.env.HEDERA_NETWORK == null 12 | ) { 13 | throw new Error( 14 | "Environment variables OPERATOR_ID, HEDERA_NETWORK, and OPERATOR_KEY are required.", 15 | ); 16 | } 17 | 18 | const provider = new LocalProvider(); 19 | 20 | const wallet = new Wallet( 21 | process.env.OPERATOR_ID, 22 | process.env.OPERATOR_KEY, 23 | provider, 24 | ); 25 | 26 | try { 27 | let transaction = await new TransferTransaction() 28 | .addHbarTransfer("0.0.3", 1) 29 | .addHbarTransfer(wallet.getAccountId(), -1) 30 | .freezeWithSigner(wallet); 31 | 32 | transaction = await transaction.signWithSigner(wallet); 33 | const response = await transaction.executeWithSigner(wallet); 34 | const receipt = await wallet.getProvider().waitForReceipt(response); 35 | 36 | console.log(`status: ${receipt.status.toString()}`); 37 | } catch (error) { 38 | console.error(error); 39 | } 40 | 41 | provider.close(); 42 | } 43 | 44 | void main(); 45 | -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@hashgraph/examples", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "compile": "echo hello", 7 | "lint": "run-s lint:*", 8 | "lint:types": "tsc", 9 | "lint:format": "prettier '*.js' '*.json' --check", 10 | "lint:js": "eslint --fix '*.js' '*.json'", 11 | "format": "prettier '*.js' '*.json' --write" 12 | }, 13 | "engines": { 14 | "node": ">=16.0.0" 15 | }, 16 | "dependencies": { 17 | "@ethersproject/abi": "^5.8.0", 18 | "@hashgraph/sdk": "link:..", 19 | "@noble/hashes": "^1.7.1", 20 | "axios": "^1.8.2", 21 | "dotenv": "^16.3.1" 22 | }, 23 | "devDependencies": { 24 | "@types/node": "^20.8.10", 25 | "@typescript-eslint/eslint-plugin": "^5.62.0", 26 | "@typescript-eslint/parser": "^5.62.0", 27 | "dpdm": "3.13.1", 28 | "eslint": "^8.49.0", 29 | "eslint-plugin-compat": "^4.2.0", 30 | "eslint-plugin-import": "^2.28.1", 31 | "eslint-plugin-jsdoc": "^46.8.2", 32 | "eslint-plugin-node": "^11.1.0", 33 | "npm-run-all": "^4.1.5", 34 | "nyc": "^15.1.0", 35 | "prettier": "^3.0.3", 36 | "typedoc": "^0.25.1", 37 | "typescript": "^5.7.2" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/payable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.8.0; 2 | 3 | contract Payable { 4 | // the contract's owner, set in the constructor 5 | address payable owner; 6 | 7 | constructor() payable { 8 | // set the owner of the contract for `kill()` 9 | owner = payable(msg.sender); 10 | } 11 | 12 | // return a string 13 | function greet() public pure returns (string memory) { 14 | return "Hello, world!"; 15 | } 16 | 17 | // recover the funds of the contract 18 | function kill() public { if (msg.sender == owner) selfdestruct(payable(msg.sender)); } 19 | } 20 | -------------------------------------------------------------------------------- /examples/precompile-example/ExpiryHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | pragma solidity >=0.5.0 <0.9.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | // This file was copied from github.com/hashgraph/hedera-smart-contracts on Sep 27 2023 6 | 7 | import "./HederaTokenService.sol"; 8 | 9 | abstract contract ExpiryHelper { 10 | 11 | function createAutoRenewExpiry( 12 | address autoRenewAccount, 13 | int64 autoRenewPeriod 14 | ) internal pure returns (IHederaTokenService.Expiry memory expiry) { 15 | expiry.autoRenewAccount = autoRenewAccount; 16 | expiry.autoRenewPeriod = autoRenewPeriod; 17 | } 18 | 19 | function createSecondExpiry(int64 second) internal pure returns (IHederaTokenService.Expiry memory expiry) { 20 | expiry.second = second; 21 | } 22 | } -------------------------------------------------------------------------------- /examples/precompile-example/IPrngSystemContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | pragma solidity >=0.4.9 <0.9.0; 3 | 4 | // This file was copied from github.com/hashgraph/hedera-smart-contracts on Aug 31 2022 5 | 6 | interface IPrngSystemContract { 7 | // Generates a 256-bit pseudorandom seed using the first 256-bits of running hash of n-3 transaction record. 8 | // Users can generate a pseudorandom number in a specified range using the seed by (integer value of seed % range) 9 | function getPseudorandomSeed() external returns (bytes32); 10 | } 11 | -------------------------------------------------------------------------------- /examples/precompile-example/PrngSystemContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // This file was copied from github.com/hashgraph/hedera-smart-contracts on Aug 31 2022 4 | 5 | import "./IPrngSystemContract.sol"; 6 | 7 | contract PrngSystemContract { 8 | // Prng system contract address with ContractID 0.0.361 9 | address constant PRECOMPILE_ADDRESS = address(0x169); 10 | 11 | function getPseudorandomSeed() external returns (bytes32 seedBytes) { 12 | (bool success, bytes memory result) = PRECOMPILE_ADDRESS.call( 13 | abi.encodeWithSelector(IPrngSystemContract.getPseudorandomSeed.selector)); 14 | require(success, "PRNG system call failed"); 15 | seedBytes = abi.decode(result, (bytes32)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/prng-transaction.js: -------------------------------------------------------------------------------- 1 | import { Wallet, LocalProvider, PrngTransaction } from "@hashgraph/sdk"; 2 | 3 | import dotenv from "dotenv"; 4 | 5 | dotenv.config(); 6 | 7 | async function main() { 8 | if ( 9 | process.env.OPERATOR_ID == null || 10 | process.env.OPERATOR_KEY == null || 11 | process.env.HEDERA_NETWORK == null 12 | ) { 13 | throw new Error( 14 | "Environment variables OPERATOR_ID, HEDERA_NETWORK, and OPERATOR_KEY are required.", 15 | ); 16 | } 17 | 18 | const provider = new LocalProvider(); 19 | 20 | const wallet = new Wallet( 21 | process.env.OPERATOR_ID, 22 | process.env.OPERATOR_KEY, 23 | provider, 24 | ); 25 | 26 | try { 27 | let transaction = await new PrngTransaction() 28 | .setRange(100) 29 | .freezeWithSigner(wallet); 30 | transaction = await transaction.signWithSigner(wallet); 31 | const response = await transaction.executeWithSigner(wallet); 32 | 33 | const record = await response.getRecordWithSigner(wallet); 34 | console.log(`The random number generated is: ${record.prngNumber}`); 35 | } catch (error) { 36 | console.error(error); 37 | } 38 | 39 | provider.close(); 40 | } 41 | 42 | void main(); 43 | -------------------------------------------------------------------------------- /examples/react-native-example/.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 4 | } 5 | -------------------------------------------------------------------------------- /examples/react-native-example/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | .env 13 | 14 | # macOS 15 | .DS_Store 16 | 17 | # @generated expo-cli sync-e7dcf75f4e856f7b6f3239b3f3a7dd614ee755a8 18 | # The following patterns were generated by expo-cli 19 | 20 | # OSX 21 | # 22 | .DS_Store 23 | 24 | # Xcode 25 | # 26 | build/ 27 | *.pbxuser 28 | !default.pbxuser 29 | *.mode1v3 30 | !default.mode1v3 31 | *.mode2v3 32 | !default.mode2v3 33 | *.perspectivev3 34 | !default.perspectivev3 35 | xcuserdata 36 | *.xccheckout 37 | *.moved-aside 38 | DerivedData 39 | *.hmap 40 | *.ipa 41 | *.xcuserstate 42 | project.xcworkspace 43 | 44 | # Android/IntelliJ 45 | # 46 | build/ 47 | .idea 48 | .gradle 49 | local.properties 50 | *.iml 51 | *.hprof 52 | 53 | # node.js 54 | # 55 | node_modules/ 56 | npm-debug.log 57 | yarn-error.log 58 | 59 | # BUCK 60 | buck-out/ 61 | \.buckd/ 62 | *.keystore 63 | !debug.keystore 64 | 65 | # Bundle artifacts 66 | *.jsbundle 67 | 68 | # CocoaPods 69 | /ios/Pods/ 70 | 71 | # Expo 72 | .expo/ 73 | web-build/ 74 | dist/ 75 | 76 | # @end expo-cli 77 | -------------------------------------------------------------------------------- /examples/react-native-example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "react-native-example", 4 | "slug": "react-native-example", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "userInterfaceStyle": "light", 9 | "splash": { 10 | "image": "./assets/splash.png", 11 | "resizeMode": "contain", 12 | "backgroundColor": "#ffffff" 13 | }, 14 | "updates": { 15 | "fallbackToCacheTimeout": 0 16 | }, 17 | "assetBundlePatterns": [ 18 | "**/*" 19 | ], 20 | "ios": { 21 | "supportsTablet": true 22 | }, 23 | "android": { 24 | "adaptiveIcon": { 25 | "foregroundImage": "./assets/adaptive-icon.png", 26 | "backgroundColor": "#FFFFFF" 27 | } 28 | }, 29 | "web": { 30 | "favicon": "./assets/favicon.png" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/react-native-example/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-sdk-js/09d2a937c4ed820b04468cd85a015739020cd33a/examples/react-native-example/assets/adaptive-icon.png -------------------------------------------------------------------------------- /examples/react-native-example/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-sdk-js/09d2a937c4ed820b04468cd85a015739020cd33a/examples/react-native-example/assets/favicon.png -------------------------------------------------------------------------------- /examples/react-native-example/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-sdk-js/09d2a937c4ed820b04468cd85a015739020cd33a/examples/react-native-example/assets/icon.png -------------------------------------------------------------------------------- /examples/react-native-example/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiero-ledger/hiero-sdk-js/09d2a937c4ed820b04468cd85a015739020cd33a/examples/react-native-example/assets/splash.png -------------------------------------------------------------------------------- /examples/react-native-example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | return { 4 | presets: ["babel-preset-expo"], 5 | plugins: [["module:react-native-dotenv"]], 6 | }; 7 | }; 8 | -------------------------------------------------------------------------------- /examples/react-native-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-example", 3 | "version": "1.0.0", 4 | "main": "node_modules/expo/AppEntry.js", 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo run:android", 8 | "ios": "expo run:ios", 9 | "web": "expo start --web", 10 | "eject": "expo eject" 11 | }, 12 | "dependencies": { 13 | "@hashgraph/sdk": "file:.yalc/@hashgraph/sdk", 14 | "expo": "~53.0.4", 15 | "expo-status-bar": "~2.0.1", 16 | "react": "19.0.0", 17 | "react-dom": "19.0.0", 18 | "react-native": "~0.78.0", 19 | "react-native-get-random-values": "^1.11.0" 20 | }, 21 | "devDependencies": { 22 | "@babel/core": "^7.23.3", 23 | "@types/react": "19.0.0", 24 | "react-native-dotenv": "^3.4.9", 25 | "typescript": "^5.7.2" 26 | }, 27 | "private": true 28 | } 29 | -------------------------------------------------------------------------------- /examples/react-native-example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/simple_rest_signature_provider/.env: -------------------------------------------------------------------------------- 1 | # Local Node 2 | OPERATOR_KEY=0xa608e2130a0a3cb34f86e757303c862bee353d9ab77ba4387ec084f881d420d4 3 | OPERATOR_ID=0.0.1022 4 | HEDERA_NETWORK=local-node 5 | 6 | TREASURY_ID=0.0.1023 7 | TREASURY_KEY=0xbbd0894de0b4ecfa862e963825c5448d2d17f807a16869526bff29185747acdb 8 | ALICE_ID=0.0.1024 9 | ALICE_KEY=0x8fd50f886a2e7ed499e7686efd1436b50aa9b64b26e4ecc4e58ca26e6257b67d 10 | BOB_ID=0.0.1025 11 | BOB_KEY=0x62c966ebd9dcc0fc16a553b2ef5b72d1dca05cdf5a181027e761171e9e947420 -------------------------------------------------------------------------------- /examples/simple_rest_signature_provider/Taskfile.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | silent: true 4 | 5 | tasks: 6 | default: 7 | deps: 8 | - build 9 | 10 | install: 11 | cmds: 12 | - pnpm i 13 | 14 | build: 15 | cmds: 16 | - task: install 17 | - task: format 18 | - task: lint 19 | 20 | clean: 21 | cmds: 22 | - rm -rf node_modules 23 | 24 | format: 25 | cmds: 26 | - ./node_modules/.bin/prettier "*.json" "src/*.js" --write > /dev/null 27 | 28 | lint: 29 | deps: 30 | - "lint:types" 31 | - "lint:format" 32 | - "lint:js" 33 | 34 | "lint:types": 35 | cmds: 36 | - ./node_modules/.bin/tsc 37 | 38 | "lint:format": 39 | cmds: 40 | - ./node_modules/.bin/prettier "*.json" "src/*.js" --check > /dev/null 41 | 42 | "lint:js": 43 | cmds: 44 | - ./node_modules/.bin/eslint --fix "src/*.js" 45 | -------------------------------------------------------------------------------- /examples/simple_rest_signature_provider/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 | -------------------------------------------------------------------------------- /examples/stateful.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.22 <0.6.0; 2 | 3 | contract StatefulContract { 4 | // the contract's owner, set in the constructor 5 | address owner; 6 | 7 | // the message we're storing 8 | string message; 9 | 10 | constructor(string memory message_) public { 11 | // set the owner of the contract for `kill()` 12 | owner = msg.sender; 13 | message = message_; 14 | } 15 | 16 | function set_message(string memory message_) public { 17 | // only allow the owner to update the message 18 | if (msg.sender != owner) return; 19 | message = message_; 20 | } 21 | 22 | // return a string 23 | function get_message() public view returns (string memory) { 24 | return message; 25 | } 26 | 27 | // recover the funds of the contract 28 | function kill() public { if (msg.sender == owner) selfdestruct(msg.sender); } 29 | } 30 | -------------------------------------------------------------------------------- /examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "lib": ["ESNext", "DOM"], 6 | "allowJs": true, 7 | "checkJs": true, 8 | "emitDeclarationOnly": false, 9 | "declaration": false, 10 | "strict": true, 11 | "strictNullChecks": false, 12 | "noImplicitAny": false, 13 | "noUnusedLocals": true, 14 | "noUnusedParameters": false, 15 | "downlevelIteration": true, 16 | "noImplicitReturns": true, 17 | "noFallthroughCasesInSwitch": true, 18 | "moduleResolution": "node", 19 | "allowSyntheticDefaultImports": true, 20 | "esModuleInterop": true, 21 | "forceConsistentCasingInFileNames": true, 22 | "resolveJsonModule": true, 23 | "noEmit": true 24 | }, 25 | "include": ["*.js", "*.json"] 26 | } 27 | -------------------------------------------------------------------------------- /manual/RELEASE.md: -------------------------------------------------------------------------------- 1 | ## Release process of JS SDK 2 | 3 | - **Create** a new release branch following the naming convention for: 4 | - stable release - `release-v*.*.*` 5 | - beta release - `release-v*.*.*-beta.*` 6 | - **Run** the [local node](https://github.com/hiero-ledger/hiero-local-node) 7 | - **Run** `task test:integration:node` 8 | - **Stop** the [local node](https://github.com/hiero-ledger/hiero-local-node) 9 | - **Run** `task test:release` (Note: the local node should not be running) 10 | - **Update** the SDK version in `package.json` file 11 | - **Update** the CHANGELOG file 12 | - **Merge** release branch into main 13 | - **Create** a new tag as running following command for: 14 | - stable release - `git tag -a "v*.*.*" -m "[message]"` 15 | - beta release - `git tag -a "v*.*.*-beta.*" -m "[message]"` 16 | - **Run** the following command for: 17 | - stable release - `git push origin v*.*.*` 18 | - beta release - `git push origin v*.*.*-beta.*` 19 | - **Monitor** the [status](https://github.com/hiero-ledger/hiero-sdk-js/actions/workflows/publish_release.yaml) of this CI pipeline -------------------------------------------------------------------------------- /packages/cryptography/.babelrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@babel/plugin-transform-modules-commonjs", 4 | "@babel/plugin-syntax-dynamic-import", 5 | [ 6 | "babel-plugin-dynamic-import-node", 7 | { 8 | "noInterop": true 9 | } 10 | ], 11 | [ 12 | "module-rewrite", 13 | { "replaceFunc": "./build/replace-module-paths.cjs" } 14 | ] 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /packages/cryptography/build/replace-module-paths.cjs: -------------------------------------------------------------------------------- 1 | // ensure that all local imports go from .js to .cjs when moved to lib/ 2 | // https://github.com/liady/babel-plugin-module-rewrite 3 | module.exports = function replaceImport(originalPath, callingFileName, options) { 4 | let path = originalPath; 5 | 6 | if (global.process != null && global.process.env != null && global.process.env.HEDERA_SDK_TEST != null) { 7 | if ( 8 | originalPath.startsWith(".") && 9 | originalPath.endsWith(".js") && 10 | !callingFileName.includes("/test/") && 11 | path.includes("/src/") 12 | ) { 13 | path = path.replace(".js", ".cjs"); 14 | path = path.replace("src/", "lib/"); 15 | } 16 | } else { 17 | if (path.startsWith(".") && path.endsWith(".js")) { 18 | path = path.replace(".js", ".cjs"); 19 | } 20 | } 21 | 22 | return path; 23 | } 24 | -------------------------------------------------------------------------------- /packages/cryptography/src/BadKeyError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Signals that a key could not be realized from the input. 3 | */ 4 | export default class BadKeyError extends Error { 5 | /** 6 | * @param {Error | string} messageOrCause 7 | */ 8 | constructor(messageOrCause) { 9 | super( 10 | messageOrCause instanceof Error 11 | ? messageOrCause.message 12 | : messageOrCause, 13 | ); 14 | 15 | this.name = "BadKeyError"; 16 | 17 | if (messageOrCause instanceof Error) { 18 | /** @type {Error=} */ 19 | this.cause = messageOrCause; 20 | this.stack = messageOrCause.stack; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/cryptography/src/BadMnemonicReason.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Possible statuses for {@link Mnemonic#validate()}. 3 | * @readonly 4 | * @enum {string} 5 | */ 6 | const BadMnemonicReason = Object.freeze({ 7 | /** 8 | * The mnemonic did not have a supported number of words (12 or 24 for regular and 22 for legacy). 9 | */ 10 | BadLength: "BadLength", 11 | 12 | /** 13 | * The mnemonic contained words which were not found in the word list. 14 | */ 15 | UnknownWords: "UnknownWords", 16 | 17 | /** 18 | * The checksum encoded in the mnemonic did not match the checksum we just calculated for 19 | * that mnemonic. 20 | * 21 | * 24-word mnemonics have an 8-bit checksum that is appended to the 32 bytes of source entropy 22 | * after being calculated from it, before being encoded into words. 23 | * 24 | * This could happen if two or more of the words were entered out of the original order or 25 | * replaced with another from the standard word list (as this is only returned if all the words 26 | * exist in the word list). 27 | */ 28 | ChecksumMismatch: "ChecksumMismatch", 29 | }); 30 | 31 | export default BadMnemonicReason; 32 | -------------------------------------------------------------------------------- /packages/cryptography/src/Cache.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @typedef {import("./PrivateKey.js").default} PrivateKey 3 | * @typedef {import("./Ed25519PrivateKey.js").default} Ed25519PrivateKey 4 | * @typedef {import("./EcdsaPrivateKey.js").default} EcdsaPrivateKey 5 | * @typedef {import("./Mnemonic.js").default} Mnemonic 6 | */ 7 | 8 | const CACHE = { 9 | /** @type {((key: Ed25519PrivateKey | EcdsaPrivateKey) => PrivateKey) | null} */ 10 | privateKeyConstructor: null, 11 | 12 | /** @type {((bytes: Uint8Array) => PrivateKey) | null} */ 13 | privateKeyFromBytes: null, 14 | 15 | /** @type {((words: string) => Mnemonic) | null} */ 16 | mnemonicFromString: null, 17 | }; 18 | 19 | export default CACHE; 20 | -------------------------------------------------------------------------------- /packages/cryptography/src/Key.js: -------------------------------------------------------------------------------- 1 | export default class Key {} 2 | -------------------------------------------------------------------------------- /packages/cryptography/src/encoding/base64.browser.js: -------------------------------------------------------------------------------- 1 | import { Buffer } from "buffer"; 2 | 3 | /** 4 | * @param {string} text 5 | * @returns {Uint8Array} 6 | */ 7 | export function decode(text) { 8 | return Uint8Array.from(Buffer.from(text, "base64")); 9 | } 10 | 11 | /** 12 | * @param {Uint8Array} data 13 | * @returns {string}; 14 | */ 15 | export function encode(data) { 16 | return Buffer.from(data).toString("base64"); 17 | } 18 | -------------------------------------------------------------------------------- /packages/cryptography/src/encoding/base64.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} text 3 | * @returns {Uint8Array} 4 | */ 5 | export function decode(text) { 6 | return Buffer.from(text, "base64"); 7 | } 8 | 9 | /** 10 | * @param {Uint8Array} data 11 | * @returns {string}; 12 | */ 13 | export function encode(data) { 14 | return Buffer.from(data).toString("base64"); 15 | } 16 | -------------------------------------------------------------------------------- /packages/cryptography/src/encoding/base64.native.js: -------------------------------------------------------------------------------- 1 | import { Buffer } from "buffer"; 2 | 3 | /** 4 | * @param {string} text 5 | * @returns {Uint8Array} 6 | */ 7 | export function decode(text) { 8 | return Uint8Array.from(Buffer.from(text, "base64")); 9 | } 10 | 11 | /** 12 | * @param {Uint8Array} data 13 | * @returns {string}; 14 | */ 15 | export function encode(data) { 16 | return Buffer.from(data).toString("base64"); 17 | } 18 | -------------------------------------------------------------------------------- /packages/cryptography/src/encoding/hex.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Uint8Array} data 3 | * @returns {string} 4 | */ 5 | export function encode(data) { 6 | return Buffer.from(data).toString("hex"); 7 | } 8 | 9 | /** 10 | * @param {string} text 11 | * @returns {Uint8Array} 12 | */ 13 | export function decode(text) { 14 | const str = text.startsWith("0x") ? text.substring(2) : text; 15 | return Buffer.from(str, "hex"); 16 | } 17 | 18 | /** 19 | * Encode with a specified length. Supports zero padding if the most significant byte is 0 20 | * 21 | * https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L315 22 | * @param {Uint8Array} value 23 | * @param {number} length 24 | * @returns {string} 25 | */ 26 | export function hexZeroPadded(value, length) { 27 | const HexCharacters = "0123456789abcdef"; 28 | 29 | // https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L243 30 | let result = "0x"; 31 | for (let i = 0; i < value.length; i++) { 32 | let v = value[i]; 33 | result += HexCharacters[(v & 0xf0) >> 4] + HexCharacters[v & 0x0f]; 34 | } 35 | 36 | // https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L315 37 | if (result.length > 2 * length + 2) { 38 | console.log("result out of range", "result"); 39 | } 40 | 41 | while (result.length < 2 * length + 2) { 42 | result = "0x0" + result.substring(2); 43 | } 44 | 45 | return result.substring(2); 46 | } 47 | -------------------------------------------------------------------------------- /packages/cryptography/src/encoding/utf8.browser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Uint8Array} data 3 | * @returns {string} 4 | */ 5 | export function decode(data) { 6 | // eslint-disable-next-line n/no-unsupported-features/node-builtins 7 | return new TextDecoder().decode(data); 8 | } 9 | 10 | /** 11 | * @param {string} text 12 | * @returns {Uint8Array} 13 | */ 14 | export function encode(text) { 15 | // eslint-disable-next-line n/no-unsupported-features/node-builtins 16 | return new TextEncoder().encode(text); 17 | } 18 | -------------------------------------------------------------------------------- /packages/cryptography/src/encoding/utf8.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Uint8Array} data 3 | * @returns {string} 4 | */ 5 | export function decode(data) { 6 | return Buffer.from(data).toString("utf8"); 7 | } 8 | 9 | /** 10 | * @param {string} text 11 | * @returns {Uint8Array} 12 | */ 13 | export function encode(text) { 14 | return Buffer.from(text, "utf8"); 15 | } 16 | -------------------------------------------------------------------------------- /packages/cryptography/src/encoding/utf8.native.js: -------------------------------------------------------------------------------- 1 | import utf8 from "utf8"; 2 | import * as hex from "./hex.native.js"; 3 | 4 | /** 5 | * @param {Uint8Array} data 6 | * @returns {string} 7 | */ 8 | export function decode(data) { 9 | return utf8.decode(hex.encodeToByteString(data)); 10 | } 11 | 12 | /** 13 | * @param {string} text 14 | * @returns {Uint8Array} 15 | */ 16 | export function encode(text) { 17 | return hex.decodeFromByteString(utf8.encode(text)); 18 | } 19 | -------------------------------------------------------------------------------- /packages/cryptography/src/index.js: -------------------------------------------------------------------------------- 1 | export { default as Key } from "./Key.js"; 2 | export { default as KeyList } from "./KeyList.js"; 3 | export { default as PrivateKey } from "./PrivateKey.js"; 4 | export { default as PublicKey } from "./PublicKey.js"; 5 | export { 6 | default as Mnemonic, 7 | HEDERA_PATH, 8 | SLIP44_ECDSA_ETH_PATH, 9 | SLIP44_ECDSA_HEDERA_PATH, 10 | } from "./Mnemonic.js"; 11 | export { default as BadKeyError } from "./BadKeyError.js"; 12 | export { default as BadMnemonicError } from "./BadMnemonicError.js"; 13 | export { default as BadMnemonicReason } from "./BadMnemonicReason.js"; 14 | -------------------------------------------------------------------------------- /packages/cryptography/src/index.native.js: -------------------------------------------------------------------------------- 1 | // Add react-native environment cryptography polyfills 2 | import "./polyfills.native.js"; 3 | 4 | export { default as Key } from "./Key.js"; 5 | export { default as KeyList } from "./KeyList.js"; 6 | export { default as PrivateKey } from "./PrivateKey.js"; 7 | export { default as PublicKey } from "./PublicKey.js"; 8 | export { 9 | default as Mnemonic, 10 | HEDERA_PATH, 11 | SLIP44_ECDSA_ETH_PATH, 12 | SLIP44_ECDSA_HEDERA_PATH, 13 | } from "./Mnemonic.js"; 14 | export { default as BadKeyError } from "./BadKeyError.js"; 15 | export { default as BadMnemonicError } from "./BadMnemonicError.js"; 16 | export { default as BadMnemonicReason } from "./BadMnemonicReason.js"; 17 | -------------------------------------------------------------------------------- /packages/cryptography/src/polyfills.native.js: -------------------------------------------------------------------------------- 1 | import "react-native-get-random-values"; 2 | global.process.nextTick = setImmediate; 3 | -------------------------------------------------------------------------------- /packages/cryptography/src/primitive/aes.js: -------------------------------------------------------------------------------- 1 | import crypto from "crypto"; 2 | import * as hex from "../encoding/hex.js"; 3 | 4 | export const CipherAlgorithm = { 5 | Aes128Ctr: "AES-128-CTR", 6 | Aes128Cbc: "AES-128-CBC", 7 | }; 8 | 9 | /** 10 | * @param {string} algorithm 11 | * @param {Uint8Array} key 12 | * @param {Uint8Array} iv 13 | * @param {Uint8Array} data 14 | * @returns {Promise} 15 | */ 16 | export function createCipheriv(algorithm, key, iv, data) { 17 | const cipher = crypto.createCipheriv(algorithm, key.slice(0, 16), iv); 18 | 19 | return Promise.resolve( 20 | Buffer.concat([cipher.update(data), cipher["final"]()]), 21 | ); 22 | } 23 | 24 | /** 25 | * @param {string} algorithm 26 | * @param {Uint8Array} key 27 | * @param {Uint8Array} iv 28 | * @param {Uint8Array} data 29 | * @returns {Promise} 30 | */ 31 | export function createDecipheriv(algorithm, key, iv, data) { 32 | const decipher = crypto.createDecipheriv(algorithm, key.slice(0, 16), iv); 33 | 34 | return Promise.resolve( 35 | Buffer.concat([decipher.update(data), decipher["final"]()]), 36 | ); 37 | } 38 | 39 | /** 40 | * @param {string} passphrase 41 | * @param {string} iv 42 | * @returns {Promise} 43 | */ 44 | export function messageDigest(passphrase, iv) { 45 | return Promise.resolve( 46 | crypto 47 | .createHash("md5") 48 | .update(passphrase) 49 | .update(hex.decode(iv).slice(0, 8)) 50 | .digest(), 51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /packages/cryptography/src/primitive/bip39.js: -------------------------------------------------------------------------------- 1 | import * as hmac from "../primitive/hmac.js"; 2 | import * as pbkdf2 from "./pbkdf2.js"; 3 | 4 | /** 5 | * @param {string[]} words 6 | * @param {string} passphrase 7 | * @returns {Promise} 8 | */ 9 | export async function toSeed(words, passphrase) { 10 | const input = words.join(" "); 11 | const salt = `mnemonic${passphrase}`.normalize("NFKD"); 12 | 13 | return pbkdf2.deriveKey(hmac.HashAlgorithm.Sha512, input, salt, 2048, 64); 14 | } 15 | -------------------------------------------------------------------------------- /packages/cryptography/src/primitive/hmac.browser.js: -------------------------------------------------------------------------------- 1 | import * as utf8 from "../encoding/utf8.js"; 2 | 3 | // this will be executed in browser environment so we can use window.crypto 4 | /* eslint-disable n/no-unsupported-features/node-builtins */ 5 | 6 | /** 7 | * @enum {string} 8 | */ 9 | export const HashAlgorithm = { 10 | Sha256: "SHA-256", 11 | Sha384: "SHA-384", 12 | Sha512: "SHA-512", 13 | }; 14 | 15 | /** 16 | * @param {HashAlgorithm} algorithm 17 | * @param {Uint8Array | string} secretKey 18 | * @param {Uint8Array | string} data 19 | * @returns {Promise} 20 | */ 21 | export async function hash(algorithm, secretKey, data) { 22 | const key = 23 | typeof secretKey === "string" ? utf8.encode(secretKey) : secretKey; 24 | const value = typeof data === "string" ? utf8.encode(data) : data; 25 | 26 | try { 27 | const key_ = await window.crypto.subtle.importKey( 28 | "raw", 29 | key, 30 | { 31 | name: "HMAC", 32 | hash: algorithm, 33 | }, 34 | false, 35 | ["sign"], 36 | ); 37 | 38 | return new Uint8Array( 39 | await window.crypto.subtle.sign("HMAC", key_, value), 40 | ); 41 | } catch { 42 | throw new Error("Fallback if SubtleCrypto fails is not implemented"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/cryptography/src/primitive/hmac.js: -------------------------------------------------------------------------------- 1 | import crypto from "crypto"; 2 | import * as utf8 from "../encoding/utf8.js"; 3 | 4 | /** 5 | * @enum {string} 6 | */ 7 | export const HashAlgorithm = { 8 | Sha256: "SHA-256", 9 | Sha384: "SHA-384", 10 | Sha512: "SHA-512", 11 | }; 12 | 13 | /** 14 | * @param {HashAlgorithm} algorithm 15 | * @param {Uint8Array | string} secretKey 16 | * @param {Uint8Array | string} data 17 | * @returns {Promise} 18 | */ 19 | export function hash(algorithm, secretKey, data) { 20 | const key = 21 | typeof secretKey === "string" ? utf8.encode(secretKey) : secretKey; 22 | const value = typeof data === "string" ? utf8.encode(data) : data; 23 | 24 | switch (algorithm) { 25 | case HashAlgorithm.Sha256: 26 | return Promise.resolve( 27 | crypto.createHmac("SHA256", key).update(value).digest(), 28 | ); 29 | case HashAlgorithm.Sha384: 30 | return Promise.resolve( 31 | crypto.createHmac("SHA384", key).update(value).digest(), 32 | ); 33 | case HashAlgorithm.Sha512: 34 | return Promise.resolve( 35 | crypto.createHmac("SHA512", key).update(value).digest(), 36 | ); 37 | default: 38 | throw new Error( 39 | "(BUG) Non-Exhaustive switch statement for algorithms", 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/cryptography/src/primitive/pbkdf2.js: -------------------------------------------------------------------------------- 1 | import { HashAlgorithm } from "./hmac.js"; 2 | import * as utf8 from "../encoding/utf8.js"; 3 | import util from "util"; 4 | import crypto from "crypto"; 5 | 6 | /** 7 | * @param {HashAlgorithm} algorithm 8 | * @param {Uint8Array | string} password 9 | * @param {Uint8Array | string} salt 10 | * @param {number} iterations 11 | * @param {number} length 12 | * @returns {Promise} 13 | */ 14 | export async function deriveKey(algorithm, password, salt, iterations, length) { 15 | const pass = 16 | typeof password === "string" 17 | ? // Valid ASCII is also valid UTF-8 so encoding the password as UTF-8 18 | // should be fine if only valid ASCII characters are used in the password 19 | utf8.encode(password) 20 | : password; 21 | 22 | const nacl = typeof salt === "string" ? utf8.encode(salt) : salt; 23 | 24 | const pbkdf2 = util.promisify(crypto.pbkdf2); 25 | 26 | switch (algorithm) { 27 | case HashAlgorithm.Sha256: 28 | return pbkdf2(pass, nacl, iterations, length, "sha256"); 29 | case HashAlgorithm.Sha384: 30 | return pbkdf2(pass, nacl, iterations, length, "sha384"); 31 | case HashAlgorithm.Sha512: 32 | return pbkdf2(pass, nacl, iterations, length, "sha512"); 33 | default: 34 | throw new Error( 35 | "(BUG) Non-Exhaustive switch statement for algorithms", 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/cryptography/src/primitive/random.js: -------------------------------------------------------------------------------- 1 | import nacl from "tweetnacl"; 2 | 3 | /** 4 | * @param {number} count 5 | * @returns {Uint8Array} 6 | */ 7 | export function bytes(count) { 8 | return nacl.randomBytes(count); 9 | } 10 | 11 | /** 12 | * @param {number} count 13 | * @returns {Promise} 14 | */ 15 | export function bytesAsync(count) { 16 | return Promise.resolve(nacl.randomBytes(count)); 17 | } 18 | -------------------------------------------------------------------------------- /packages/cryptography/src/primitive/sha256.browser.js: -------------------------------------------------------------------------------- 1 | // this will be executed in browser environment so we can use window.crypto 2 | /* eslint-disable n/no-unsupported-features/node-builtins */ 3 | 4 | /** 5 | * @param {Uint8Array} data 6 | * @returns {Promise} 7 | */ 8 | export async function digest(data) { 9 | // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest 10 | return new Uint8Array(await crypto.subtle.digest("SHA-256", data)); 11 | } 12 | -------------------------------------------------------------------------------- /packages/cryptography/src/primitive/sha256.js: -------------------------------------------------------------------------------- 1 | import crypto from "crypto"; 2 | 3 | /** 4 | * @param {Uint8Array} data 5 | * @returns {Promise} 6 | */ 7 | // eslint-disable-next-line @typescript-eslint/require-await 8 | export async function digest(data) { 9 | // fallback to trying node-crypto which could be polyfilled by the browser environment 10 | return crypto.createHash("sha256").update(data).digest(); 11 | } 12 | -------------------------------------------------------------------------------- /packages/cryptography/src/primitive/sha256.native.js: -------------------------------------------------------------------------------- 1 | import CryptoJS from "crypto-js"; 2 | import * as hex from "../encoding/hex.js"; 3 | 4 | /** 5 | * @param {Uint8Array} data 6 | * @returns {Promise} 7 | */ 8 | // eslint-disable-next-line @typescript-eslint/require-await 9 | export async function digest(data) { 10 | return Promise.resolve( 11 | hex.decode( 12 | CryptoJS.SHA256(CryptoJS.enc.Hex.parse(hex.encode(data))).toString( 13 | CryptoJS.enc.Hex, 14 | ), 15 | ), 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /packages/cryptography/src/primitive/slip10.js: -------------------------------------------------------------------------------- 1 | import * as hmac from "../primitive/hmac.js"; 2 | import * as bip32 from "../primitive/bip32.js"; 3 | 4 | /** 5 | * @param {Uint8Array} parentKey 6 | * @param {Uint8Array} chainCode 7 | * @param {number} index 8 | * @returns {Promise<{ keyData: Uint8Array; chainCode: Uint8Array }>} 9 | */ 10 | export async function derive(parentKey, chainCode, index) { 11 | if (bip32.isHardenedIndex(index)) { 12 | throw new Error("the index should not be pre-hardened"); 13 | } 14 | 15 | const input = new Uint8Array(37); 16 | 17 | // 0x00 + parentKey + index(BE) 18 | input[0] = 0; 19 | input.set(parentKey, 1); 20 | new DataView(input.buffer, input.byteOffset, input.byteLength).setUint32( 21 | 33, 22 | index, 23 | false, 24 | ); 25 | 26 | // set the index to hardened 27 | input[33] |= 128; 28 | 29 | const digest = await hmac.hash(hmac.HashAlgorithm.Sha512, chainCode, input); 30 | 31 | return { keyData: digest.subarray(0, 32), chainCode: digest.subarray(32) }; 32 | } 33 | 34 | /** 35 | * @param {Uint8Array} seed 36 | * @returns {Promise<{ keyData: Uint8Array; chainCode: Uint8Array }>} 37 | */ 38 | export async function fromSeed(seed) { 39 | const digest = await hmac.hash( 40 | hmac.HashAlgorithm.Sha512, 41 | "ed25519 seed", 42 | seed, 43 | ); 44 | 45 | return { keyData: digest.subarray(0, 32), chainCode: digest.subarray(32) }; 46 | } 47 | -------------------------------------------------------------------------------- /packages/cryptography/src/primitive/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Byte comparison utility 3 | * @param {Uint8Array} a 4 | * @param {Uint8Array} b 5 | * @returns {boolean} 6 | */ 7 | export function equalBytes(a, b) { 8 | if (a.length !== b.length) { 9 | return false; 10 | } 11 | 12 | for (let i = 0; i < a.length; i++) { 13 | if (a[i] !== b[i]) return false; 14 | } 15 | return true; 16 | } 17 | -------------------------------------------------------------------------------- /packages/cryptography/src/util/array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Uint8Array} array1 3 | * @param {Uint8Array} array2 4 | * @returns {boolean} 5 | */ 6 | export function arrayEqual(array1, array2) { 7 | if (array1 === array2) { 8 | return true; 9 | } 10 | 11 | if (array1.byteLength !== array2.byteLength) { 12 | return false; 13 | } 14 | 15 | const view1 = new DataView( 16 | array1.buffer, 17 | array1.byteOffset, 18 | array1.byteLength, 19 | ); 20 | const view2 = new DataView( 21 | array2.buffer, 22 | array2.byteOffset, 23 | array2.byteLength, 24 | ); 25 | 26 | let i = array1.byteLength; 27 | 28 | while (i--) { 29 | if (view1.getUint8(i) !== view2.getUint8(i)) { 30 | return false; 31 | } 32 | } 33 | 34 | return true; 35 | } 36 | 37 | /** 38 | * @param {Uint8Array} array 39 | * @param {Uint8Array} arrayPrefix 40 | * @returns {boolean} 41 | */ 42 | export function arrayStartsWith(array, arrayPrefix) { 43 | if (array.byteLength < arrayPrefix.byteLength) { 44 | return false; 45 | } 46 | 47 | let i = arrayPrefix.byteLength; 48 | 49 | while (i--) { 50 | if (array[i] !== arrayPrefix[i]) { 51 | return false; 52 | } 53 | } 54 | 55 | return true; 56 | } 57 | -------------------------------------------------------------------------------- /packages/cryptography/src/util/derive.js: -------------------------------------------------------------------------------- 1 | import * as pbkdf2 from "../primitive/pbkdf2.js"; 2 | import * as hmac from "../primitive/hmac.js"; 3 | 4 | /** 5 | * @param {Uint8Array} seed 6 | * @param {number} index 7 | * @returns {Promise} 8 | */ 9 | export function legacy(seed, index) { 10 | const password = new Uint8Array(seed.length + 8); 11 | password.set(seed, 0); 12 | 13 | const view = new DataView( 14 | password.buffer, 15 | password.byteOffset, 16 | password.byteLength, 17 | ); 18 | 19 | if (index === 0xffffffffff) { 20 | view.setInt32(seed.length + 0, 0xff); 21 | view.setInt32(seed.length + 4, -1); // 0xffffffff 22 | } else { 23 | view.setInt32(seed.length + 0, index < 0 ? -1 : 0); 24 | view.setInt32(seed.length + 4, index); 25 | } 26 | 27 | const salt = Uint8Array.from([0xff]); 28 | return pbkdf2.deriveKey( 29 | hmac.HashAlgorithm.Sha512, 30 | password, 31 | salt, 32 | 2048, 33 | 32, 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /packages/cryptography/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 | parserOptions: { 11 | requireConfigFile: false, 12 | ecmaVersion: 2020, 13 | sourceType: "module", 14 | }, 15 | extends: ["eslint:recommended"], 16 | globals: { 17 | expect: "readonly", 18 | describe: "readonly", 19 | it: "readonly", 20 | beforeAll: "readonly", 21 | afterAll: "readonly", 22 | beforeEach: "readonly", 23 | afterEach: "readonly", 24 | }, 25 | rules: { 26 | "vitest/valid-expect": "off", 27 | "vitest/expect-expect": "off", 28 | "vitest/valid-title": "off", 29 | "vitest/no-disabled-tests": "warn", 30 | }, 31 | }; 32 | -------------------------------------------------------------------------------- /packages/cryptography/test/node_modules: -------------------------------------------------------------------------------- 1 | ../node_modules -------------------------------------------------------------------------------- /packages/cryptography/test/src: -------------------------------------------------------------------------------- 1 | ../src -------------------------------------------------------------------------------- /packages/cryptography/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"] 18 | } 19 | -------------------------------------------------------------------------------- /packages/cryptography/test/unit/KeyList.js: -------------------------------------------------------------------------------- 1 | import PublicKey from "../../src/PublicKey.js"; 2 | import KeyList from "../../src/KeyList.js"; 3 | 4 | describe("KeyList", function () { 5 | it("KeyList.toString()", async function () { 6 | const key1 = PublicKey.fromString( 7 | "302a300506032b65700321008f41f9476ded1bfb887ef49b40b2a33c97c9a90324e79ce53465e15968bb4503", 8 | ); 9 | const key2 = PublicKey.fromString( 10 | "302a300506032b6570032100bbb3991523f8145f1cf4b90c7b57bfa60f42d07547aaf979fddd69388d210f6c", 11 | ); 12 | const key3 = PublicKey.fromString( 13 | "302a300506032b6570032100f169271fe46f43ba29a786c170359e71c69eb34354e90d0b8c1e2b4b317cc650", 14 | ); 15 | 16 | const keys = KeyList.of(key1, key2, key3); 17 | 18 | const string = 19 | '{"threshold":null,"keys":"302a300506032b65700321008f41f9476ded1bfb887ef49b40b2a33c97c9a90324e79ce53465e15968bb4503,302a300506032b6570032100bbb3991523f8145f1cf4b90c7b57bfa60f42d07547aaf979fddd69388d210f6c,302a300506032b6570032100f169271fe46f43ba29a786c170359e71c69eb34354e90d0b8c1e2b4b317cc650"}'; 20 | 21 | expect(keys.toString()).to.be.equal(string); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /packages/cryptography/test/unit/encoding/base64.js: -------------------------------------------------------------------------------- 1 | import * as base64 from "../../../src/encoding/base64.js"; 2 | import * as utf8 from "../../../src/encoding/utf8.js"; 3 | 4 | // from RFC 4648 5 | const vectors = [ 6 | ["", ""], 7 | ["f", "Zg=="], 8 | ["fo", "Zm8="], 9 | ["foo", "Zm9v"], 10 | ["foob", "Zm9vYg=="], 11 | ["fooba", "Zm9vYmE="], 12 | ["foobar", "Zm9vYmFy"], 13 | ]; 14 | 15 | describe("encoding/base64", function () { 16 | it("should encode", function () { 17 | for (const [decoded, encoded] of vectors) { 18 | expect(base64.encode(utf8.encode(decoded))).to.equal(encoded); 19 | } 20 | }); 21 | 22 | it("should decode", function () { 23 | for (const [decoded, encoded] of vectors) { 24 | expect(utf8.decode(base64.decode(encoded))).to.equal(decoded); 25 | } 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/cryptography/test/unit/encoding/hex-native.js: -------------------------------------------------------------------------------- 1 | import * as hex from "../../../src/encoding/hex.native.js"; 2 | 3 | const bytes = new Uint8Array([ 4 | -37, 72, 75, -126, -114, 100, -78, -40, -15, 44, -29, -64, -96, -23, 58, 11, 5 | -116, -50, 122, -15, -69, -113, 57, -55, 119, 50, 57, 68, -126, 83, -114, 6 | 16, 7 | ]); 8 | 9 | const string = 10 | "db484b828e64b2d8f12ce3c0a0e93a0b8cce7af1bb8f39c97732394482538e10"; 11 | 12 | describe("encoding/hex", function () { 13 | it("should encode", function () { 14 | expect(hex.encode(bytes)).to.deep.equal(string); 15 | }); 16 | 17 | it("should decode", function () { 18 | expect(hex.decode(string)).to.deep.equal(bytes); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/cryptography/test/unit/encoding/hex.js: -------------------------------------------------------------------------------- 1 | import * as hex from "../../../src/encoding/hex.js"; 2 | 3 | const bytes = new Uint8Array([ 4 | -37, 72, 75, -126, -114, 100, -78, -40, -15, 44, -29, -64, -96, -23, 58, 11, 5 | -116, -50, 122, -15, -69, -113, 57, -55, 119, 50, 57, 68, -126, 83, -114, 6 | 16, 7 | ]); 8 | 9 | const string = 10 | "db484b828e64b2d8f12ce3c0a0e93a0b8cce7af1bb8f39c97732394482538e10"; 11 | 12 | describe("encoding/hex", function () { 13 | it("should encode", function () { 14 | expect(hex.encode(bytes)).to.deep.equal(string); 15 | }); 16 | 17 | it("should decode", function () { 18 | expect(hex.decode(string)).to.deep.equal(bytes); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/cryptography/test/unit/keystore.js: -------------------------------------------------------------------------------- 1 | export const keystoreV1 = `{"version":1,"crypto":{"ciphertext":"92e133ced8d2d0a5b13334e24c436145f182d7d3188799dab73348577aa6b525c8f5a39550ef08a956968c2a515ac6be131c0281e8e48914a1c89fbfa381c420","cipherparams":{"iv":"d17926abd3fbd429ecaaf8cfd285ee63"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dkLen":32,"salt":"7d1f4b77d8ad55a2903171ed324cf1cd032f105a9495af15994f3a4cf6cd4361","c":262144,"prf":"hmac-sha256"},"mac":"b2daf12be1b3d5326b1cd8c72f51781ef155054b4c8c3087489d78a3330e2f28b86e6d3967982ad1823eab00cb6c6763"}}`; 2 | -------------------------------------------------------------------------------- /packages/cryptography/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: [ 11 | "test/unit/keystore.js", 12 | "test/unit/primitive/aes.browser.js", 13 | ], 14 | testTimeout: 8000, 15 | coverage: { 16 | provider: "v8", 17 | include: ["src/**/*.js"], 18 | reporter: ["text-summary", "lcov"], 19 | reportsDirectory: "./coverage", 20 | }, 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /packages/cryptography/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "lib": ["ESNext", "DOM"], 6 | "allowJs": true, 7 | "checkJs": true, 8 | "declaration": true, 9 | "emitDeclarationOnly": true, 10 | "outDir": "lib/", 11 | "rootDir": "src/", 12 | "strict": true, 13 | "noImplicitAny": true, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 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 | -------------------------------------------------------------------------------- /packages/proto/.babelrc.json: -------------------------------------------------------------------------------- 1 | { 2 | // "presets": ["minify"], 3 | "plugins": [ 4 | "@babel/plugin-transform-modules-commonjs", 5 | "@babel/plugin-syntax-dynamic-import", 6 | [ 7 | "babel-plugin-dynamic-import-node", 8 | { 9 | "noInterop": true 10 | } 11 | ] 12 | ], 13 | "comments": false 14 | } 15 | -------------------------------------------------------------------------------- /packages/proto/.eslintignore: -------------------------------------------------------------------------------- 1 | src/proto.js 2 | -------------------------------------------------------------------------------- /packages/proto/.gitignore: -------------------------------------------------------------------------------- 1 | src/proto.js 2 | src/proto.d.ts 3 | src/services -------------------------------------------------------------------------------- /packages/proto/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120 3 | } 4 | -------------------------------------------------------------------------------- /packages/proto/src/index.d.ts: -------------------------------------------------------------------------------- 1 | import * as $protobuf from "protobufjs/minimal.js"; 2 | import { proto, com, google } from "./proto.js"; 3 | 4 | import Reader = $protobuf.Reader; 5 | import Writer = $protobuf.Writer; 6 | 7 | export { Reader, Writer, proto, com, google }; 8 | -------------------------------------------------------------------------------- /packages/proto/src/index.js: -------------------------------------------------------------------------------- 1 | import * as $protobuf from "protobufjs/minimal.js"; 2 | import Long from "long"; 3 | 4 | import * as $proto from "./proto.js"; 5 | 6 | /** 7 | * Patch protobuf race condition between loading protobuf and Long.js libraries. 8 | */ 9 | (() => { 10 | var $util = $protobuf.util; 11 | 12 | if ($util.Long == null) { 13 | console.log(`Patching Protobuf Long.js instance...`); 14 | $util.Long = Long; 15 | 16 | if ($protobuf.Reader._configure != null) { 17 | // eslint-disable-next-line @typescript-eslint/no-unsafe-call 18 | $protobuf.Reader._configure($protobuf.BufferReader); 19 | } 20 | } 21 | })(); 22 | 23 | export const Reader = $protobuf.Reader; 24 | export const Writer = $protobuf.Writer; 25 | 26 | export const proto = $proto.proto; 27 | export const com = $proto.com; 28 | export const google = $proto.google; 29 | -------------------------------------------------------------------------------- /packages/proto/src/proto/sdk/transaction_list.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package proto; 4 | 5 | option java_package = "com.hedera.hashgraph.sdk.proto"; 6 | option java_multiple_files = true; 7 | 8 | import "transaction.proto"; 9 | 10 | /** 11 | * A simple protobuf wrapper to store a list of transactions. This is used by 12 | * `Transaction.[from|to]Bytes()` in the SDKs. The reason the SDK needs a list of transactions is 13 | * because it holds onto a transaction per node. So if a transaction is to be submitted to nodes 3 14 | * and 4 the SDK Transaction type would contain a list of 2 protobuf transactions, one for node 3 15 | * and one for node 4. 16 | */ 17 | message TransactionList { 18 | repeated Transaction transaction_list = 1; 19 | } 20 | -------------------------------------------------------------------------------- /packages/proto/src/proto/services/auxiliary/hints/crs_publication.proto: -------------------------------------------------------------------------------- 1 | /** 2 | * # hinTS Key Publication Transaction 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.services.auxiliary.hints; 14 | 15 | // SPDX-License-Identifier: Apache-2.0 16 | option java_package = "com.hedera.hapi.services.auxiliary.hints.legacy"; 17 | // <<>> This comment is special code for setting PBJ Compiler java package 18 | 19 | option java_multiple_files = true; 20 | 21 | /** 22 | * A transaction body to publish a node's Common Reference String (CRS) to the network. This is used 23 | * when node wants to update to reach the final CRS for network to use the hinTS protocol 24 | */ 25 | message CrsPublicationTransactionBody { 26 | /** 27 | * The party's generated random CRS. 28 | */ 29 | bytes new_crs = 1; 30 | /** 31 | * The party's proof of the CRS update. 32 | */ 33 | bytes proof = 2; 34 | } 35 | -------------------------------------------------------------------------------- /packages/proto/src/proto/services/auxiliary/hints/hints_partial_signature.proto: -------------------------------------------------------------------------------- 1 | /** 2 | * # hinTS Partial Signature Transaction 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.services.auxiliary.hints; 14 | 15 | // SPDX-License-Identifier: Apache-2.0 16 | option java_package = "com.hedera.hapi.services.auxiliary.hints.legacy"; 17 | // <<>> This comment is special code for setting PBJ Compiler java package 18 | 19 | option java_multiple_files = true; 20 | 21 | /** 22 | * A transaction body to publish a node's hinTS partial signature on 23 | * a particular message for a certain construction id. 24 | */ 25 | message HintsPartialSignatureTransactionBody { 26 | /** 27 | * The id of the hinTS construction this partial signature applies to. 28 | * (The size of the target roster for this construction implies what 29 | * hinTS party id the submitting node has in the construction; and 30 | * hence also what weight the node's signature has.) 31 | */ 32 | uint64 construction_id = 1; 33 | 34 | /** 35 | * The message being signed. 36 | */ 37 | bytes message = 2; 38 | 39 | /** 40 | * The node's partial signature on the message. 41 | */ 42 | bytes partial_signature = 3; 43 | } 44 | -------------------------------------------------------------------------------- /packages/proto/src/proto/services/auxiliary/history/history_proof_key_publication.proto: -------------------------------------------------------------------------------- 1 | /** 2 | * # Proof Key Publication Transaction 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.services.auxiliary.history; 14 | 15 | // SPDX-License-Identifier: Apache-2.0 16 | option java_package = "com.hedera.hapi.services.auxiliary.history.legacy"; 17 | // <<>> This comment is special code for setting PBJ Compiler java package 18 | 19 | option java_multiple_files = true; 20 | 21 | /** 22 | * A transaction body to publish a node's history proof key. 23 | */ 24 | message HistoryProofKeyPublicationTransactionBody { 25 | /** 26 | * The proof key the submitting node intends to use when 27 | * contributing signatures for use in proving history 28 | * belongs to the chain of trust for the ledger id. 29 | */ 30 | bytes proof_key = 1; 31 | } 32 | -------------------------------------------------------------------------------- /packages/proto/src/proto/services/auxiliary/history/history_proof_signature.proto: -------------------------------------------------------------------------------- 1 | /** 2 | * # Metadata Proof Assembly Signature Transaction 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.services.auxiliary.history; 14 | 15 | // SPDX-License-Identifier: Apache-2.0 16 | import "services/state/history/history_types.proto"; 17 | 18 | option java_package = "com.hedera.hapi.services.auxiliary.history.legacy"; 19 | // <<>> This comment is special code for setting PBJ Compiler java package 20 | 21 | option java_multiple_files = true; 22 | 23 | /** 24 | * A transaction body to publish a node's signature on a computed 25 | * history of address book hash and associated metadata. This 26 | * signature can contribute to a proof that the history belongs to 27 | * to the chain of trust for the ledger id. 28 | */ 29 | message HistoryProofSignatureTransactionBody { 30 | /** 31 | * The id of the proof construction this signature is contributing to. 32 | */ 33 | uint64 construction_id = 1; 34 | 35 | /** 36 | * This node's signature on its computed history. 37 | */ 38 | com.hedera.hapi.node.state.history.HistorySignature signature = 2; 39 | } 40 | -------------------------------------------------------------------------------- /packages/proto/src/proto/services/auxiliary/history/history_proof_vote.proto: -------------------------------------------------------------------------------- 1 | /** 2 | * # Metadata Proof Vote Transaction 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.services.auxiliary.history; 14 | 15 | // SPDX-License-Identifier: Apache-2.0 16 | import "services/state/history/history_types.proto"; 17 | 18 | option java_package = "com.hedera.hapi.services.auxiliary.history.legacy"; 19 | // <<>> This comment is special code for setting PBJ Compiler java package 20 | 21 | option java_multiple_files = true; 22 | 23 | /** 24 | * A transaction body to publish a node's vote for a 25 | * proof of history associated to a construction id. 26 | */ 27 | message HistoryProofVoteTransactionBody { 28 | /** 29 | * The id of the proof construction this vote is for. 30 | */ 31 | uint64 construction_id = 1; 32 | 33 | /** 34 | * The submitting node's vote on the history proof. 35 | */ 36 | com.hedera.hapi.node.state.history.HistoryProofVote vote = 2; 37 | } 38 | -------------------------------------------------------------------------------- /packages/proto/src/proto/services/auxiliary/tss/tss_encryption_key.proto: -------------------------------------------------------------------------------- 1 | /** 2 | * # Tss Encryption Key Transaction 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.services.auxiliary.tss; 14 | 15 | // SPDX-License-Identifier: Apache-2.0 16 | option java_package = "com.hedera.hapi.services.auxiliary.tss.legacy"; 17 | // <<>> 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 | --------------------------------------------------------------------------------