How to Approve Fungible Token and NFT Allowances on Hedera –… | Hedera Hedera Network Services Token Service Mint and configure tokens and accounts. Consensus Service Verifiable timestamps and ordering of events. Smart Contracts Run Solidity smart contracts. HBAR The Hedera network's native cryptocurrency. Insights How It Works Learn about Hedera from end to end. Explorers View live and historical data on Hedera. Dashboards Analyze network activity and metrics. Network Nodes Understand networks and node types. Devs Start Building Get Started Learn core concepts and build the future. Documentation Review the API and build using your favorite language. Developer Resources Integrations Plugins and microservices for Hedera. Fee Estimator Understand and estimate transaction costs. Open Source Hedera is committed to open, transparent code. Learning Center Learn about web3 and blockchain technologies. Grants Grants & accelerators for your project. Bounties Find bugs. Submit a report. Earn rewards. Ecosystem ECOSYSTEM Hedera Ecosystem Applications, developer tools, network explorers, and more. NFT Ecosystem Metrics Analyze on-chain and market NFT ecosystem metrics. CATEGORIES Web3 Applications Connect into the innovative startups decentralizing the web on Hedera. Enterprise Applications Learn about the Fortune 500 companies decentralizing the web on Hedera. Wallets & Custodians Create a Hedera account to manage HBAR, fungible tokens, and NFTs. Network Explorers Hedera mainnet and testnet graphical network explorers. Developer Tooling Third-party APIs, integrations, and plugins to build apps on Hedera. Grants & Accelerators Boost your project with support from the Hedera ecosystem. Partner Program Explore our partners to bring your vision into reality. Hedera Council Over 30 highly diversified organizations govern Hedera. Use Cases Hedera Solutions Asset Tokenization Studio Open source toolkit for tokenizing assets securely. Stablecoin Studio All-in-one toolkit for stablecoin solutions. Hedera Guardian Auditable carbon markets and traceability. Functional Use Cases Data Integrity & AI Reliable, secure, and ethically governed insights. Sustainability Enabling fair carbon markets with trust. Real-World Asset Tokenization Seamless tokenization of real-world assets and digital at scale. Consumer Engagement & Loyalty Mint, distribute, and redeem loyalty rewards. Decentralized Identity Maintain the lifecycle of credentials. Decentralized Logs Scalable, real-time timestamped events. DeFi Dapps built for the next-generation of finance. NFTs Low, fixed fees. Immutable royalties. Payments Scalable, real-time, and affordable crypto-payments. HBAR Overview Learn about Hedera's token, HBAR. Treasury Management Hedera’s report of the HBAR supply. Governance Decentralized Governance Hedera Council See the world's leading organizations that own Hedera. About Meet Hedera's Board of Directors and team. Journey Watch Hedera's journey to build an empowered digital future for all. Transparent Governance Public Policy Hedera's mission is to inform policy and regulation that impact the industry. Meeting Minutes Immutably recorded on Hedera. Roadmap Follow Hedera's roadmap in its journey to build the future. Resources Company What's New Partners Papers Careers Media Blog Technical Press Podcast Community Events Meetups Store Brand Navigation QUICKSTART How to Approve Fungible Token and NFT Allowances on Hedera – Part 1: Using the SDK technical Oct 10, 2022 by Ed Marquez Head of Developer Relations Allowances grant another account (spender) the right to transfer HBAR, fungible tokens (FT), and non-fungible tokens (NFTs) from your account (owner). The ability to approve allowances is important because it enables applications like exchanges and wallets to perform transfers on behalf of their customers without requiring a customer to sign every single transaction in advance. You can approve allowances and perform approved transfers on Hedera as you build things like NFT exchanges, marketplaces for carbon assets, games, and more. This tutorial series shows you how to approve allowances for fungible tokens and NFTs. Part 1 focuses on approving token allowances using the Hedera JavaScript SDK. Part 2 and Part 3 show how to approve token allowances using Solidity HTS precompiles and ERC standard calls, respectively. To learn how to approve HBAR allowances, check out How to Approve HBAR Allowances on Hedera Using the SDK. Try It Yourself Get a Hedera testnet account This portal acts like a faucet, giving you 10,000 test HBAR every 24 hours Use this Codesandbox to try the example Fork the sandbox Remember to provide testnet account credentials in the .env file Open a new terminal to execute index_ft.js or index_nft.js Get the example code from GitHub Example: Alice Spends FT and NFT on Behalf of the Treasury This example guides you through the following steps: Creating additional Hedera accounts and native tokens (Treasury, Alice, Bob, and the HBAR ROCKS token) Treasury approving an allowance of HBAR ROCKS tokens for Alice (50 FT / 3 NFT) Alice performing an approved token transfer from Treasury to Bob (45 FT / 1 NFT) Treasury deleting the token allowance for Alice After completing all steps, your console should look something like this (for FT/NFT): Fungible token example output (left) and NFT example output (right) 1. Create Accounts and HTS Token There are five entities in this scenario: Operator, Treasury, Alice, Bob, and the HBAR ROCKS token. Your testnet credentials from the Hedera portal should be used for the operator variables, which are used to initialize the Hedera client that submits transactions to the network and gets confirmations. Create new accounts for Treasury, Alice, and Bob. Start by specifying the initial balance of each new account (initBalance) to be 10 HBAR Generate and record the private key for each account. Hedera supports ED25519 and ECDSA keys Use the function accountCreateFcn to create the new accounts The function returns the status of the transaction (treasurySt) and the new account ID (treasuryId The inputs are the newly generated private key (treasuryKey), initBalance, and the client object Output to the console a link to the mirror node explorer, HashScan, showing information about the new accounts console.log(`\nSTEP 1 ===================================\n`); console.log(`- Creating Hedera accounts...\n`); const initBalance = new Hbar(10); const treasuryKey = PrivateKey.generateECDSA(); const [treasurySt, treasuryId] = await accountCreateFcn(treasuryKey, initBalance, client); console.log(`- Treasury's account: https://hashscan.io/#/testnet/account/${treasuryId}`); const aliceKey = PrivateKey.generateECDSA(); const [aliceSt, aliceId] = await accountCreateFcn(aliceKey, initBalance, client); console.log(`- Alice's account: https://hashscan.io/#/testnet/account/${aliceId}`); const bobKey = PrivateKey.generateECDSA(); const [bobSt, bobId] = await accountCreateFcn(bobKey, initBalance, client); console.log(`- Bob's account: https://hashscan.io/#/testnet/account/${bobId}`); Copy The code tabs below show the functions called to create the FT (htsTokens.createFtFcn) and NFT (htsTokens.createMintNftFcn). Both functions return the ID of the new token (tokenId), and token information from a query (tokenInfo) For creation of the FT, the inputs are the token name (HBAR ROCKS), token symbol (HROCK), the initial supply (100), the treasury account for the token (treasuryId), the treasury key for transaction authorization (treasuryKey), and the client object For the NFT creation, the inputs are the token name (HBAR ROCKS), token symbol (HROCK), the initial supply (0), the maximum token supply (1000), the treasury account for the token (treasuryId), the treasury key for transaction authorization (treasuryKey), and the client object Output to the console tokenId and the token supply Fungible Token (FT) Fungible Token (FT) Non-Fungible Token (NFT) const [tokenId, tokenInfo] = await htsTokens.createFtFcn("HBAR ROCKS", "HROCK", 100, treasuryId, treasuryKey, client); console.log(`\n- Token ID: ${tokenId}`); console.log(`- Initial token supply: ${tokenInfo.totalSupply.low}`); const [tokenId, tokenInfo] = await htsTokens.createMintNftFcn("HBAR ROCKS", "HROCK", 0, 1000, treasuryId, treasuryKey, client); console.log(`\n- Token ID: ${tokenId}`); console.log(`- Token supply after minting NFTs: ${tokenInfo.totalSupply.low}`); Helper Functions The helper function accountCreateFcn uses the AccountCreateTransaction() class of the SDK to generate the new accounts for Treasury, Alice, and Bob. The functions htsTokens.createFtFcn and htsTokens.createMintNftFcn both use the TokenCreateTransaction() class of the SDK. However, each instance is customized appropriately to create a fungible or non-fungible token. In the NFT case, the helper function also uses the TokenMintTransaction() class to mint a batch of 5 NFTs in a single transaction. For additional details on using the Hedera Token Service (HTS) for fungible and non-fungible tokens, be sure to read the tutorial series Get Started with the Hedera Token Service. You can easily reuse the helper functions in this example in case you need to do tasks like creating more accounts or tokens in the future. We’ll use this modular approach throughout the article. accountCreateFcn accountCreateFcn htsTokens.createFtFcn htsTokens.createMintNftFcn queries.tokenQueryFcn async function accountCreateFcn(pvKey, iBal, client) { const response = await new AccountCreateTransaction() .setInitialBalance(iBal) .setKey(pvKey.publicKey) .setAlias(pvKey.publicKey.toEvmAddress()) .setMaxAutomaticTokenAssociations(10) .execute(client); const receipt = await response.getReceipt(client); return [receipt.status, receipt.accountId]; } export async function createFtFcn(tName, tSymbol, iSupply, id, pvKey, client) { const tokenCreateTx = new TokenCreateTransaction() .setTokenName(tName) .setTokenSymbol(tSymbol) .setDecimals(0) .setInitialSupply(iSupply) .setTreasuryAccountId(id) .setAdminKey(pvKey.publicKey) .setSupplyKey(pvKey.publicKey) .freezeWith(client); const tokenCreateSign = await tokenCreateTx.sign(pvKey); const tokenCreateSubmit = await tokenCreateSign.execute(client); const tokenCreateRx = await tokenCreateSubmit.getReceipt(client); const tokenId = tokenCreateRx.tokenId; const tokenInfo = await queries.tokenQueryFcn(tokenId, client); return [tokenId, tokenInfo]; } export async function createMintNftFcn(tName, tSymbol, iSupply, maxSupply, id, pvKey, client) { const nftCreate = new TokenCreateTransaction() .setTokenName(tName) .setTokenSymbol(tSymbol) .setTokenType(TokenType.NonFungibleUnique) .setSupplyType(TokenSupplyType.Finite) .setDecimals(0) .setInitialSupply(iSupply) .setTreasuryAccountId(id) .setSupplyKey(pvKey.publicKey) .setMaxSupply(maxSupply) // .setCustomFees([nftCustomFee]) // .setAdminKey(adminKey) // .setPauseKey(pauseKey) // .setFreezeKey(freezeKey) // .setWipeKey(wipeKey) .freezeWith(client); const nftCreateTxSign = await nftCreate.sign(pvKey); const nftCreateSubmit = await nftCreateTxSign.execute(client); const nftCreateRx = await nftCreateSubmit.getReceipt(client); const tokenId = nftCreateRx.tokenId; // // MINT NEW BATCH OF NFTs const CID = [ Buffer.from("ipfs://QmNPCiNA3Dsu3K5FxDPMG5Q3fZRwVTg14EXA92uqEeSRXn"), Buffer.from("ipfs://QmZ4dgAgt8owvnULxnKxNe8YqpavtVCXmc1Lt2XajFpJs9"), Buffer.from("ipfs://QmPzY5GxevjyfMUF5vEAjtyRoigzWp47MiKAtLBduLMC1T"), Buffer.from("ipfs://Qmd3kGgSrAwwSrhesYcY7K54f3qD7MDo38r7Po2dChtQx5"), Buffer.from("ipfs://QmWgkKz3ozgqtnvbCLeh7EaR1H8u5Sshx3ZJzxkcrT3jbw"), ]; const mintTx = new TokenMintTransaction() .setTokenId(tokenId) .setMetadata(CID) //Batch minting - UP TO 10 NFTs in single tx .freezeWith(client); const mintTxSign = await mintTx.sign(pvKey); const mintTxSubmit = await mintTxSign.execute(client); const mintRx = await mintTxSubmit.getReceipt(client); const tokenInfo = await queries.tokenQueryFcn(tokenId, client); return [tokenId, tokenInfo]; } export async function tokenQueryFcn(tkId, client) { let info = await new TokenInfoQuery().setTokenId(tkId).execute(client); return info; } Console Output (FT/NFT): 2. Approve FT / NFT Allowance From the token creation and minting in the previous step, Treasury has an HBAR ROCK balance of 100 FT / 5 NFT. The allowance amount approved for Alice to spend on behalf of Treasury (allowBal) is 50 in the case of the fungible token - and serials #1, #2, and #3 in the case of the NFT For the fungible token example, use the function approvals.ftAllowanceFcn to approve the allowance The function returns the receipt object of the transaction (allowanceApproveFtRx) The inputs are tokenId, the owner account ID (treasuryId), the spender account ID (aliceId), allowBal, the private key of the owner for transaction authorization (treasuryKey), and client For the NFT example, use the function approvals.nftAllowanceFcn to approve the allowance Serials #1, #2, and #3 of the NFT are specified using he NftId class of the SDK The function returns the receipt object of the transaction (allowanceApproveNftRx) The inputs are tokenId, treasuryId, aliceId, the array of NFTs to approve (nft2approve), treasuryKey, and client Output to the console: The status of the allowance approval transaction A mirror node REST API request that shows fungible token allowances approved by Treasury Account balances using queries.balanceCheckerFcn Fungible Token (FT) Fungible Token (FT) Non-Fungible Token (NFT) console.log(`\nSTEP 2 ===================================\n`); console.log(`- Treasury approving fungible token allowance for Alice...\n`); let allowBal = 50; const allowanceApproveFtRx = await approvals.ftAllowanceFcn(tokenId, treasuryId, aliceId, allowBal, treasuryKey, client); console.log(`- Allowance approval status: ${allowanceApproveFtRx.status}`); console.log(`- https://testnet.mirrornode.hedera.com/api/v1/accounts/${treasuryId}/allowances/tokens \n`); console.log(`\nSTEP 2 ===================================\n`); console.log(`- Treasury approving NFT allowance for Alice...\n`); // Can approve all serials under a NFT collection // Or can approve individual serials under a NFT collection const nft1 = new NftId(tokenId, 1); const nft2 = new NftId(tokenId, 2); const nft3 = new NftId(tokenId, 3); const nft2approve = [nft1, nft2, nft3]; const allowanceApproveNftRx = await approvals.nftAllowanceFcn(tokenId, treasuryId, aliceId, nft2approve, treasuryKey, client); console.log(`- Allowance approval status: ${allowanceApproveNftRx.status}`); await queries.balanceCheckerFcn(treasuryId, tokenId, client); await queries.balanceCheckerFcn(aliceId, tokenId, client); await queries.balanceCheckerFcn(bobId, tokenId, client); Copy Helper functions The helper functions approvals.ftAllowanceFcn and approvals.nftAllowanceFcn both use AccountAllowanceApproveTransaction() from the SDK to grant the token allowances for the spender from an owner’s account balance. The difference is the methods used - .approveTokenAllowance() is used to approve fungible token allowances, whereas .approveTokenNftAllowance() is used to approve NFT allowances by serial number. Note that for NFTs you also have the option to approve all serial numbers by using the .approveTokenNftAllowanceAllSerials() method. The function queries.balanceCheckerFcn uses AccountBalanceQuery() to check and display the HBAR and token balances for a given account ID or contract ID. approvals.ftAllowanceFcn approvals.ftAllowanceFcn approvals.nftAllowanceFcn queries.balanceCheckerFcn export async function ftAllowanceFcn(tId, owner, spender, allowBal, pvKey, client) { const allowanceTx = new AccountAllowanceApproveTransaction().approveTokenAllowance(tId, owner, spender, allowBal).freezeWith(client); const allowanceSign = await allowanceTx.sign(pvKey); const allowanceSubmit = await allowanceSign.execute(client); const allowanceRx = await allowanceSubmit.getReceipt(client); return allowanceRx; } export async function nftAllowanceFcn(tId, owner, spender, nft2Approve, pvKey, client) { const allowanceTx = new AccountAllowanceApproveTransaction() // .approveTokenNftAllowanceAllSerials(tId, owner, spender) // Can approve all serials under a NFT collection .approveTokenNftAllowance(nft2Approve[0], owner, spender) // Or can approve individual serials under a NFT collection .approveTokenNftAllowance(nft2Approve[1], owner, spender) .approveTokenNftAllowance(nft2Approve[2], owner, spender) .freezeWith(client); const allowanceSign = await allowanceTx.sign(pvKey); const allowanceSubmit = await allowanceSign.execute(client); const allowanceRx = await allowanceSubmit.getReceipt(client); return allowanceRx; } export async function balanceCheckerFcn(acId, tkId, client) { let balanceCheckTx = []; try { balanceCheckTx = await new AccountBalanceQuery().setAccountId(acId).execute(client); console.log( `- Balance of account ${acId}: ${balanceCheckTx.hbars.toString()} + ${balanceCheckTx.tokens._map.get( tkId.toString() )} unit(s) of token ${tkId}` ); } catch { balanceCheckTx = await new AccountBalanceQuery().setContractId(acId).execute(client); console.log( `- Balance of contract ${acId}: ${balanceCheckTx.hbars.toString()} + ${balanceCheckTx.tokens._map.get( tkId.toString() )} unit(s) of token ${tkId}` ); } } Console Output (FT/NFT): 3. Perform Approved Token Transfer In this step, Alice spends tokens from the allowance granted by Treasury. This means that Alice transfers tokens from Treasury’s account to Bob’s. To perform an approved transfer of 45 fungible tokens (sendBal), use the function transfers.ftAllowanceFcn The function returns the receipt object of the transaction (allowanceSendFtRx) The inputs are tokenId, the owner account ID (treasuryId), the receiver account ID (bobId), sendBal, the spender account ID (aliceId), the private key of the spender for transaction authorization (aliceKey), and client To perform an approved transfer of NFT serial #3 (nft3), use the function transfers.nftAllowanceFcn The function returns the receipt object of the transaction (allowanceSendNftRx) The inputs are treasuryId, bobId, nft3, aliceId, aliceKey, and client For both cases, output to the console: The status of the approved transfer transaction Account balances using queries.balanceCheckerFcn Fungible Token (FT) Fungible Token (FT) Non-Fungible Token (NFT) console.log(`\nSTEP 3 ===================================\n`); console.log(`- Alice performing allowance transfer from Treasury to Bob...\n`); const sendBal = 45; // Spender must generate the TX ID or be the client const allowanceSendFtRx = await transfers.ftAllowanceFcn(tokenId, treasuryId, bobId, sendBal, aliceId, aliceKey, client); console.log(`- Allowance transfer status: ${allowanceSendFtRx.status} \n`); console.log(`\nSTEP 3 ===================================\n`); console.log(`- Alice performing allowance transfer from Treasury to Bob...\n`); const allowanceSendNftRx = await transfers.nftAllowanceFcn(treasuryId, bobId, nft3, aliceId, aliceKey, client); console.log(`- Allowance transfer status: ${allowanceSendNftRx.status} \n`); await queries.balanceCheckerFcn(treasuryId, tokenId, client); await queries.balanceCheckerFcn(aliceId, tokenId, client); await queries.balanceCheckerFcn(bobId, tokenId, client); Copy Helper functions The functions transfers.ftAllowanceFcn and transfers.nftAllowanceFcn both use TransferTransaction() from the SDK to enable a spender to use an allowance approved by an owner. Notice the following: The methods .addApprovedTokenTransfer() and .addApprovedNftTransfer() are used to specify the amount of fungible token or NFT serial # coming out of the owner’s account, respectively The spender must either generate the transaction ID or be the client submitting the transaction for the approved transfer to be successful In this case, .setTransactionId(TransactionId.generate(spender)) generates the transaction ID with the spender and sets it for the transfer transaction The transaction must be signed with the spender’s private key transfers.ftAllowanceFcn transfers.ftAllowanceFcn transfers.nftAllowanceFcn export async function ftAllowanceFcn(tId, owner, receiver, sendBal, spender, spenderPvKey, client) { const approvedSendTx = new TransferTransaction() .addApprovedTokenTransfer(tId, owner, -sendBal) .addTokenTransfer(tId, receiver, sendBal) .setTransactionId(TransactionId.generate(spender)) // Spender must generate the TX ID or be the client .freezeWith(client); const approvedSendSign = await approvedSendTx.sign(spenderPvKey); const approvedSendSubmit = await approvedSendSign.execute(client); const approvedSendRx = await approvedSendSubmit.getReceipt(client); return approvedSendRx; } export async function nftAllowanceFcn(owner, receiver, nft2Send, spender, spenderPvKey, client) { const approvedSendTx = new TransferTransaction() .addApprovedNftTransfer(nft2Send, owner, receiver) .setTransactionId(TransactionId.generate(spender)) // Spender must generate the TX ID or be the client .freezeWith(client); const approvedSendSign = await approvedSendTx.sign(spenderPvKey); const approvedSendSubmit = await approvedSendSign.execute(client); const approvedSendRx = await approvedSendSubmit.getReceipt(client); return approvedSendRx; } Console Output (FT/NFT): 4. Delete FT/NFT Allowance In this step, Treasury removes the token allowances for Alice. Fungible token allowances are removed by simply setting the allowance value to zero. On the other hand, NFT allowances are removed by specifying the NFT serials that should be disallowed. The function approvals.ftAllowanceFcn from before is used again for the fungible token, but now passing a value of 0 HBAR (allowBal) For the NFT scenario, call the function approvals.nftAllowanceDeleteFcn The function returns the receipt object of the transaction (allowanceDeleteNftRx) The inputs are treasuryId, an array of NFTs to disallow (nft2disallow), the private key of the owner for transaction authorization (treasuryKey), and client Output to the console: Status of the allowance deletion transaction A mirror node REST API request that shows fungible token allowances for Treasury The last step is to join the Hedera Developer Discord! Fungible Token (FT) Fungible Token (FT) Non-Fungible Token (NFT) console.log(`\nSTEP 4 ===================================\n`); console.log(`- Treasury deleting fungible token allowance for Alice...\n`); allowBal = 0; const allowanceDeleteFtRx = await approvals.ftAllowanceFcn(tokenId, treasuryId, aliceId, allowBal, treasuryKey, client); console.log(`- Allowance deletion status: ${allowanceDeleteFtRx.status}`); console.log(`- https://testnet.mirrornode.hedera.com/api/v1/accounts/${treasuryId}/allowances/tokens`); console.log(`\nSTEP 4 ===================================\n`); console.log(`- Treasury deleting NFT allowance for Alice...\n`); const nft2disallow = [nft1, nft2]; const allowanceDeleteNftRx = await approvals.nftAllowanceDeleteFcn(treasuryId, nft2disallow, treasuryKey, client); console.log(`- Allowance deletion status: ${allowanceDeleteNftRx.status}`); console.log(` ==================================================== THE END - NOW JOIN: https://hedera.com/discord ====================================================\n`); Copy Helper functions The function approvals.nftAllowanceDeleteFcn uses AccountAllowanceDeleteTransaction() from the SDK to remove an allowance previously approved by an owner. Keep in mind that 20 is the maximum number of NFT serials that can be disallowed in a single transaction. export async function nftAllowanceDeleteFcn(owner, nft2disallow, pvKey, client) { const allowanceTx = new AccountAllowanceDeleteTransaction() .deleteAllTokenNftAllowances(nft2disallow[0], owner) .deleteAllTokenNftAllowances(nft2disallow[1], owner) .freezeWith(client); const allowanceSign = await allowanceTx.sign(pvKey); const allowanceSubmit = await allowanceSign.execute(client); const allowanceRx = await allowanceSubmit.getReceipt(client); return allowanceRx; } Copy Console Output (FT/NFT): Summary Now you know how to approve allowances for fungible tokens and NFTs on Hedera using the JavaScript SDK. You can try this example with the other officially supported SDKs for Java, Go, and Swift. In Part 2 and Part 3 of this tutorial series, you will learn how to approve token allowances using Solidity HTS precompiles and ERC standard call. Continue Learning Open a Testnet Account Try Examples and Tutorials Join the Developer Discord Read the Learning Center Share This Back to blog What is gRPC, gRPC-Web, and Proxies? Ed Marquez Pragmatic Blockchain Design Patterns – Integrating Blockchain into Business Processes Michiel Mulders Zero Cost EthereumTransaction on Success: Hedera's New Fee Model for Relay Operators Oliver Thorn Hedera Adopts Chainlink Standard for Cross-Chain Interoperability To Accelerate Ecosystem Adoption Hedera Team Hedera Developer Highlights March 2025 Michiel Mulders Hedera Release Cycle Overview Ed Marquez View All Posts Sign up for the newsletter CONNECT WITH US Transparency Open Source Audits & Standards Sustainability Commitment Carbon Offsets Governance Hedera Council Public Policy Treasury Management Meeting Minutes LLC Agreement Node Requirements Community Events Meetups HBAR Telegram Developer Discord Twitter Community Support FAQ Network Status Developer Discord StackOverflow Brand Brand Guidelines Built on Hedera Logo Hedera Store About Team Partners Journey Roadmap Careers Contact General Inquiry Public Relations © 2018-2025 Hedera Hashgraph, LLC. All trademarks and company names are the property of their respective owners. All rights in the Deutsche Telekom mark are protected by Deutsche Telekom AG. All rights reserved. Hedera uses the third party marks with permission. Terms of Use  |  Privacy Policy