{"id":15739,"date":"2023-06-27T15:43:00","date_gmt":"2023-06-27T15:43:00","guid":{"rendered":"https:\/\/hederav2stg.wpenginepowered.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/"},"modified":"2025-12-08T18:25:44","modified_gmt":"2025-12-08T18:25:44","slug":"develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration","status":"publish","type":"post","link":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/","title":{"rendered":"Develop a Hedera DApp with MetaMask, HashPack, and Blade Integration"},"content":{"rendered":"<div class=\"body-text BodyCopy mb-40 style-1\">\n<p dir=\"ltr\">In the dynamic world of decentralized applications (DApps), catering to users with diverse wallet preferences is important. With the increasing adoption of blockchain technology, individuals utilize various wallet solutions to manage their digital assets. Hedera has taken a significant stride towards inclusivity by introducing MetaMask support through the groundbreaking <a href=\"https:\/\/hips.hedera.com\/hip\/hip-583\">HIP-583<\/a>. This integration offers an exciting opportunity for Ethereum Virtual Machine (EVM) users to seamlessly transition to the robust and scalable Hedera ecosystem.<\/p>\n<p dir=\"ltr\">In this step-by-step guide to DApp development, you will unlock the full potential of multi-wallet Hedera DApps. Armed with React, Material UI, Ethers, and TypeScript, you will be guided through creating a Hedera DApp. By leveraging the power of the <a href=\"https:\/\/github.com\/a-ridley\/cra-hedera-dapp-template\">Create React App (CRA) Hedera DApp template<\/a>, designed to simplify your development journey, you can integrate popular wallets such as MetaMask, Hashpack, and Blade.<\/p>\n<p dir=\"ltr\">We&#8217;ll use the Mirror Node API and Hedera Token Service (HTS) throughout this tutorial. You&#8217;ll gain invaluable insights into querying the mirror node and incorporating HTS functionality into your DApp, allowing users to manage and transact with HTS tokens effortlessly. With this approach, you will have a comprehensive understanding of MetaMask integration and be equipped with the necessary tools to develop your own DApp from start to finish.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Prerequisites\u00a0<\/h4>\n<ul>\n<li>A Hedera Testnet Account. Don&#8217;t have one?\u00a0\n<ul>\n<li>Get one at <a href=\"https:\/\/portal.hedera.com\/register\">https:\/\/portal.hedera.com\/register<\/a> and receive 10,000 test HBAR every 24 hours<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4 class=\"color-ultraviolet\">Recommended (optional)<br \/><\/h4>\n<ul>\n<li>React Framework<\/li>\n<li>HTML, CSS, and fundamental TypeScript knowledge<\/li>\n<li>REST API experience<\/li>\n<li>Node v.18+<\/li>\n<\/ul>\n<h4 class=\"color-ultraviolet\">Learning Objectives<\/h4>\n<ul>\n<li>Query the mirror\u00a0node for account token balance, token information, and Non-fungible information.<\/li>\n<li>Query the mirror node to check if the receiver has associated\u00a0with a token ID.<\/li>\n<li>Associate with HTS tokens with MetaMask, Hashpack, and Blade.<\/li>\n<li>Transfer an HTS token with MetaMask, Hashpack, and Blade.<\/li>\n<\/ul>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Screenshot-2023-06-28-at-8.35.36-PM_2023-06-29-033713_rhag.png\" alt=\"\n\n<p>Completed dApp<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>Completed dApp<\/p>\n<\/figcaption><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>We choose to\u00a0scaffold our project by using the CRA Hedera DApp template, as it offers:<\/p>\n<ul>\n<li>Multi-wallet\u00a0integration out of the box (HashPack, Blade, and MetaMask)<\/li>\n<li>Mirror Node Client<\/li>\n<li>State management via React Context<\/li>\n<li>Material UI<\/li>\n<li>Choice of TypeScript or JavaScript<\/li>\n<\/ul>\n<p>This custom\u00a0template eliminates setup overhead and allows you to dive straight into the core features of your project.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>The complete\u00a0TypeScript DApp can be found:\u00a0<a href=\"https:\/\/github.com\/hedera-dev\/multi-wallet-hedera-transfer-dapp\/tree\/completed\">https:\/\/github.com\/hedera-dev\/&#8230;<\/a><br \/>The complete JavaScript DApp can be found:\u00a0<a href=\"https:\/\/github.com\/hedera-dev\/multi-wallet-hedera-transfer-dapp-js\/tree\/completed\">https:\/\/github.com\/hedera-dev\/&#8230;<\/a><\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Scaffold your project<\/h4>\n<p class=\"inline-p\">To begin, execute the following command, replacing <\/p>\n<p class=\"codeInline\">&lt;my-app-name&gt;\u00a0<\/p>\n<p>with the directory name you wish to create for the new project:<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">npx create-react-app <my-app-name> --template git+ssh:\/\/git@github.com\/hedera-dev\/cra-hedera-dapp-template.git\n<\/code><\/pre>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/output-cra.png\" alt=\"\n\n<p>Output when scaffolding your project<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>Output when scaffolding your project<\/p>\n<\/figcaption><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>This command will generate a Create React App project with the Hedera DApp template. Once the project is generated, you can open it in your preferred code editor.<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/cra-file-directory.png\" alt=\"\n\n<p>Create React App Hedera DApp Template File Directory<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>Create React App Hedera DApp Template File Directory<\/p>\n<\/figcaption><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Fetching\u00a0Token Data: Writing Mirror Node API Queries<\/h4>\n<p>Mirror nodes offer access to historical data from the public ledger while optimizing the utilization of network resources. You can effortlessly retrieve essential information like transactions, records, events, and balances. Mirror Node API docs are found <a href=\"https:\/\/testnet.mirrornode.hedera.com\/api\/v1\/docs\/#\/accounts\/getAccountByIdOrAliasOrEvmAddress\">here<\/a>.<\/p>\n<p class=\"inline-p\">The template includes a mirror node client located at\u00a0<\/p>\n<p class=\"codeInline\">src\/services\/wallets\/mirrorNodeClient.ts\u00a0<\/p>\n<\/p>\n<p>This client is specifically configured to target Testnet and provides a predefined query for retrieving account information. We will utilize and expand upon this file throughout the tutorial to help us obtain information about the tokens we currently own.<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">import { AccountId } from \"@hashgraph\/sdk\";\nimport { NetworkConfig } from \"..\/..\/config\";\n\nexport class MirrorNodeClient {\n  url: string;\n  constructor(networkConfig: NetworkConfig) {\n    this.url = networkConfig.mirrorNodeUrl;\n  }\n\n  async getAccountInfo(accountId: AccountId) {\n    const accountInfo = await fetch(`${this.url}\/api\/v1\/accounts\/${accountId}`, { method: \"GET\" });\n    const accountInfoJson = await accountInfo.json();\n    return accountInfoJson;\n  }\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Query\u00a0Account Token Balances by Account ID<\/h4>\n<p>The information we want to pull from the mirror node is as follows:<\/p>\n<ul>\n<li>What tokens do we currently own?<\/li>\n<li>How many of those tokens do we own?<\/li>\n<\/ul>\n<p>A token is uniquely identified by its token ID, and we will refer to the number of tokens we own as a balance.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\">To represent the shape of data returned by our mirror node query, let&#8217;s create an interface outside of the\u00a0<span class=\"codeInline\">MirrorNodeClient\u00a0<\/span>class in\u00a0<\/p>\n<p class=\"codeInline\">src\/services\/wallets\/mirrorNodeClient.ts<\/p>\n<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">export interface MirrorNodeAccountTokenBalance {\n  balance: number,\n  token_id: string,\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>This interface will allow us to define the specific data fields we need for our DApp, excluding any additional data returned by the HTTP response that is not relevant to our use case.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Next, within the MirrorNodeClient class, construct an HTTP GET request using fetch and call the following Mirror Node API endpoint:<\/p>\n<\/p>\n<pre>\/api\/v1\/accounts\/{idOrAliasorEVMAddress}\/tokens?limit=100<\/pre>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\"> \/\/ Purpose: get token balances for an account\n \/\/ Returns: an array of MirrorNodeAccountTokenBalance\n async getAccountTokenBalances(accountId: AccountId) {\n   \/\/ get token balances\n   const tokenBalanceInfo = await fetch(`${this.url}\/api\/v1\/accounts\/${accountId}\/tokens?limit=100`, { method: \"GET\" });\n   const tokenBalanceInfoJson = await tokenBalanceInfo.json();\n\n   const tokenBalances = [...tokenBalanceInfoJson.tokens] as MirrorNodeAccountTokenBalance[];\n\n   \/\/ because the mirror node API paginates results, we need to check if there are more results\n   \/\/ if links.next is not null, then there are more results and we need to fetch them until links.next is null\n   let nextLink = tokenBalanceInfoJson.links.next;\n   while (nextLink !== null) {\n     const nextTokenBalanceInfo = await fetch(`${this.url}${nextLink}`, { method: \"GET\" });\n     const nextTokenBalanceInfoJson = await nextTokenBalanceInfo.json();\n     tokenBalances.push(...nextTokenBalanceInfoJson.tokens);\n     nextLink = nextTokenBalanceInfoJson.links.next;\n   }\n\n   return tokenBalances;\n }\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\">The HTTP GET request returns the response in JSON format. We store the JSON response in the variable<\/p>\n<p class=\"codeInline\">tokenBalanceInfoJson<\/p>\n<p class=\"inline-p\">.\u00a0<\/p>\n<p class=\"inline-p\">Then cast\u00a0<\/p>\n<p class=\"codeInline\">tokenBalanceInfoJson.tokens\u00a0<\/p>\n<p class=\"inline-p\">array to\u00a0<\/p>\n<p class=\"codeInline\">MirrorNodeAccountTokenBalance[]<\/p>\n<p class=\"inline-p\">.\u00a0<\/p>\n<p>This allows us to work with the token balance data in a strongly typed manner, making it easier to manipulate and use in our DApp.<\/p>\n<p class=\"inline-p\">It is important to note that the Mirror Node API paginates its results.\u00a0To ensure we fetch all the token balance information, we will check the\u00a0<\/p>\n<p class=\"codeInline\">links.next\u00a0<\/p>\n<p class=\"inline-p\">field.\u00a0<\/p>\n<p class=\"inline-p\">Once\u00a0<\/p>\n<p class=\"codeInline\">links.next\u00a0<\/p>\n<p class=\"inline-p\">is null, we can be certain that we have retrieved all the relevant token balance information. Finally, this function will return an array of\u00a0<\/p>\n<p class=\"codeInline\">MirrorNodeAccountTokenBalance\u00a0<\/p>\n<p class=\"inline-p\">containing the complete set of token balance data.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Query Token Information by Token ID<\/h4>\n<p>In addition to balance and token ID, we need more information about the tokens.\u00a0<\/p>\n<p>We want to know:<\/p>\n<ul>\n<li>What type of token is it? Non-Fungible Token (NFT) or Fungible Token (FT)?<\/li>\n<li>How many decimals does our FT have?<\/li>\n<li>What is the token name and symbol?<\/li>\n<\/ul>\n<p>We must construct a new HTTP request to query the mirror node for this token information.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\">In\u00a0<\/p>\n<p class=\"codeInline\" dir=\"ltr\">src\/services\/wallets\/mirrorNodeClient.ts<\/p>\n<p class=\"inline-p\">,\u00a0under the\u00a0<\/p>\n<p class=\"codeInline\" dir=\"ltr\">MirrorNodeAccountTokenBalance\u00a0<\/p>\n<p class=\"inline-p\">interface, create a new interface to represent the shape of data we get from our new mirror node query. <\/p>\n<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">export interface MirrorNodeTokenInfo {\n  type: 'FUNGIBLE_COMMON' | 'NON_FUNGIBLE_UNIQUE',\n  decimals: string,\n  name: string,\n  symbol: string\n  token_id: string,\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Remember that this HTTP response will return additional data, and our interface only reflects the necessary data we need for our DApp.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Next, construct the HTTP GET request using fetch and call the following Mirror Node API endpoint:\u00a0<\/p>\n<\/p>\n<pre>\/api\/v1\/tokens\/{tokenId}<\/pre>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">\/\/ Purpose: get token info for a token\n\/\/ Returns: a MirrorNodeTokenInfo \nasync getTokenInfo(tokenId: string) {\n  const tokenInfo = await fetch(`${this.url}\/api\/v1\/tokens\/${tokenId}`, { method: \"GET\" });\n  const tokenInfoJson = await tokenInfo.json() as MirrorNodeTokenInfo;\n  return tokenInfoJson;\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\">Like our previous function, after receiving the HTTP response, we parse the JSON data using the <\/p>\n<p class=\"codeInline\">.json()<\/p>\n<p class=\"inline-p\"> method. Then, we explicitly cast the parsed data as MirrorNodeTokenInfo\u00a0type.<\/p>\n<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Query\u00a0Account NFT Information by Account ID<\/h4>\n<p>In our previous function, we obtained token information; our next objective is to retrieve an account\u2019s NFT information. We will construct a separate HTTP request to fetch all the NFT information on our account.\u00a0<\/p>\n<p>What we want to know is:<\/p>\n<ul>\n<li>Which NFT serial numbers do we own?<\/li>\n<\/ul>\n<p>Create a new interface to represent what the new HTTP response returns.<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">export interface MirrorNodeNftInfo {\n  token_id: string,\n  serial_number: number,\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Then, construct an HTTP GET request and call the Mirror Node API endpoint:<\/p>\n<\/p>\n<pre>\/api\/v1\/accounts\/{accountId}\/nfts?limit=100<\/pre>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">\/\/ Purpose: get NFT Infor for an account\n\/\/ Returns: an array of NFTInfo\nasync getNftInfo(accountId: AccountId) {\n  const nftInfo = await fetch(`${this.url}\/api\/v1\/accounts\/${accountId}\/nfts?limit=100`, { method: \"GET\" });\n  const nftInfoJson = await nftInfo.json();\n\n  const nftInfos = [...nftInfoJson.nfts] as MirrorNodeNftInfo[];\n\n  \/\/ because the mirror node API paginates results, we need to check if there are more results\n  \/\/ if links.next is not null, then there are more results and we need to fetch them until links.next is null\n  let nextLink = nftInfoJson.links.next;\n  while (nextLink !== null) {\n    const nextNftInfo = await fetch(`${this.url}${nextLink}`, { method: \"GET\" });\n    const nextNftInfoJson = await nextNftInfo.json();\n    nftInfos.push(...nextNftInfoJson.nfts);\n    nextLink = nextNftInfoJson.links.next;\n  }\n  return nftInfos;\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Similar to our `getAccountTokenBalances()` function, we must ensure we fetch all the token balance information. We will check the `links.next` field until it is null.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Unify\u00a0Account Token Balances and Token Information through Query Data Aggregation<\/h4>\n<p>We need to combine all of our HTTP response data in order to display our available tokens in our DApp. Let\u2019s create the following interface to represent the combined data.<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">export interface MirrorNodeAccountTokenBalanceWithInfo extends MirrorNodeAccountTokenBalance {\n  info: MirrorNodeTokenInfo,\n  nftSerialNumbers?: number[],\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Finally, we will create a function that combines token balances, token information, and NFT information. The function will perform the following main steps:<\/p>\n<ol>\n<li>Retrieve all token balances for the specified account.<\/li>\n<li>Fetch detailed token information for each token.<\/li>\n<li>Retrieve NFT information for the account.<\/li>\n<li>Create a mapping of token IDs to their respective NFT serial numbers.<\/li>\n<li>Combine token balances, token information, and NFT information.<\/li>\n<li>Return the combined data of type <strong class=\"codeInline\">MirrorNodeAccountTokenBalance<\/strong>.<\/li>\n<\/ol>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">\/\/ Purpose: get token balances for an account with token info in order to display token balance, token type, decimals, etc.\n\/\/ Returns: an array of MirrorNodeAccountTokenBalanceWithInfo\nasync getAccountTokenBalancesWithTokenInfo(accountId: AccountId): Promise<MirrorNodeAccountTokenBalanceWithInfo[]> {\n  \/\/1.  Retrieve all token balances in the account\n  const tokens = await this.getAccountTokenBalances(accountId);\n  \/\/2. Create a map of token IDs to token info and fetch token info for each token\n  const tokenInfos = new Map<string, MirrorNodeTokenInfo>();\n  for (const token of tokens) {\n    const tokenInfo = await this.getTokenInfo(token.token_id);\n    tokenInfos.set(tokenInfo.token_id, tokenInfo);\n  }\n\n  \/\/3. Fetch all NFT info in account\n  const nftInfos = await this.getNftInfo(accountId);\n\n  \/\/4. Create a map of token Ids to arrays of serial numbers\n  const tokenIdToSerialNumbers = new Map<string, number[]>();\n  for (const nftInfo of nftInfos) {\n    const tokenId = nftInfo.token_id;\n    const serialNumber = nftInfo.serial_number;\n\n    \/\/ if we haven't seen this token_id before, create a new array with the serial number\n    if (!tokenIdToSerialNumbers.has(tokenId)) {\n      tokenIdToSerialNumbers.set(tokenId, [serialNumber]);\n    } else {\n      \/\/ if we have seen this token_id before, add the serial number to the array\n      tokenIdToSerialNumbers.get(tokenId)!.push(serialNumber);\n    }\n  }\n\n  \/\/5. Combine token balances, token info, and NFT info and return\n  return tokens.map(token => {\n    return {\n      ...token,\n      info: tokenInfos.get(token.token_id)!,\n      nftSerialNumbers: tokenIdToSerialNumbers.get(token.token_id)\n    }\n  });\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\">Below is the complete<\/p>\n<p class=\"codeInline\">mirrorNodeClient.ts<\/p>\n<p class=\"inline-p\">file, which includes all the functions we have created so far to interact with the Mirror Node API and retrieve the necessary data for our DApp. The file should look like this at this stage of the tutorial.<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">import { AccountId } from \"@hashgraph\/sdk\";\nimport { NetworkConfig } from \"..\/..\/config\";\n\nexport interface MirrorNodeAccountTokenBalance {\n  balance: number,\n  token_id: string,\n}\n\nexport interface MirrorNodeTokenInfo {\n  type: 'FUNGIBLE_COMMON' | 'NON_FUNGIBLE_UNIQUE',\n  decimals: string,\n  name: string,\n  symbol: string\n  token_id: string,\n}\n\nexport interface MirrorNodeNftInfo {\n  token_id: string,\n  serial_number: number,\n}\n\nexport interface MirrorNodeAccountTokenBalanceWithInfo extends MirrorNodeAccountTokenBalance {\n  info: MirrorNodeTokenInfo,\n  nftSerialNumbers?: number[],\n}\n\nexport class MirrorNodeClient {\n  url: string;\n  constructor(networkConfig: NetworkConfig) {\n    this.url = networkConfig.mirrorNodeUrl;\n  }\n\n\n\n  \/\/ Purpose: get token balances for an account\n  \/\/ Returns: an array of MirrorNodeAccountTokenBalance\n  async getAccountTokenBalances(accountId: AccountId) {\n    \/\/ get token balances\n    const tokenBalanceInfo = await fetch(`${this.url}\/api\/v1\/accounts\/${accountId}\/tokens?limit=100`, { method: \"GET\" });\n    const tokenBalanceInfoJson = await tokenBalanceInfo.json();\n\n    const tokenBalances = [...tokenBalanceInfoJson.tokens] as MirrorNodeAccountTokenBalance[];\n\n    \/\/ because the mirror node API paginates results, we need to check if there are more results\n    \/\/ if links.next is not null, then there are more results and we need to fetch them until links.next is null\n    let nextLink = tokenBalanceInfoJson.links.next;\n    while (nextLink !== null) {\n      const nextTokenBalanceInfo = await fetch(`${this.url}${nextLink}`, { method: \"GET\" });\n      const nextTokenBalanceInfoJson = await nextTokenBalanceInfo.json();\n      tokenBalances.push(...nextTokenBalanceInfoJson.tokens);\n      nextLink = nextTokenBalanceInfoJson.links.next;\n    }\n\n    return tokenBalances;\n  }\n\n  \/\/ Purpose: get token info for a token\n  \/\/ Returns: a MirrorNodeTokenInfo \n  async getTokenInfo(tokenId: string) {\n    const tokenInfo = await fetch(`${this.url}\/api\/v1\/tokens\/${tokenId}`, { method: \"GET\" });\n    const tokenInfoJson = await tokenInfo.json() as MirrorNodeTokenInfo;\n    return tokenInfoJson;\n  }\n\n  \/\/ Purpose: get NFT Infor for an account\n  \/\/ Returns: an array of NFTInfo\n  async getNftInfo(accountId: AccountId) {\n    const nftInfo = await fetch(`${this.url}\/api\/v1\/accounts\/${accountId}\/nfts?limit=100`, { method: \"GET\" });\n    const nftInfoJson = await nftInfo.json();\n\n    const nftInfos = [...nftInfoJson.nfts] as MirrorNodeNftInfo[];\n\n    \/\/ because the mirror node API paginates results, we need to check if there are more results\n    \/\/ if links.next is not null, then there are more results and we need to fetch them until links.next is null\n    let nextLink = nftInfoJson.links.next;\n    while (nextLink !== null) {\n      const nextNftInfo = await fetch(`${this.url}${nextLink}`, { method: \"GET\" });\n      const nextNftInfoJson = await nextNftInfo.json();\n      nftInfos.push(...nextNftInfoJson.nfts);\n      nextLink = nextNftInfoJson.links.next;\n    }\n    return nftInfos;\n  }\n\n  \/\/ Purpose: get token balances for an account with token info in order to display token balance, token type, decimals, etc.\n  \/\/ Returns: an array of MirrorNodeAccountTokenBalanceWithInfo\n  async getAccountTokenBalancesWithTokenInfo(accountId: AccountId): Promise<MirrorNodeAccountTokenBalanceWithInfo[]> {\n    \/\/1.  Retrieve all token balances in the account\n    const tokens = await this.getAccountTokenBalances(accountId);\n    \/\/2. Create a map of token IDs to token info and fetch token info for each token\n    const tokenInfos = new Map<string, MirrorNodeTokenInfo>();\n    for (const token of tokens) {\n      const tokenInfo = await this.getTokenInfo(token.token_id);\n      tokenInfos.set(tokenInfo.token_id, tokenInfo);\n    }\n\n    \/\/3. Fetch all NFT info in account\n    const nftInfos = await this.getNftInfo(accountId);\n\n    \/\/4. Create a map of token Ids to arrays of serial numbers\n    const tokenIdToSerialNumbers = new Map<string, number[]>();\n    for (const nftInfo of nftInfos) {\n      const tokenId = nftInfo.token_id;\n      const serialNumber = nftInfo.serial_number;\n\n      \/\/ if we haven't seen this token_id before, create a new array with the serial number\n      if (!tokenIdToSerialNumbers.has(tokenId)) {\n        tokenIdToSerialNumbers.set(tokenId, [serialNumber]);\n      } else {\n        \/\/ if we have seen this token_id before, add the serial number to the array\n        tokenIdToSerialNumbers.get(tokenId)!.push(serialNumber);\n      }\n    }\n\n    \/\/5. Combine token balances, token info, and NFT info and return\n    return tokens.map(token => {\n      return {\n        ...token,\n        info: tokenInfos.get(token.token_id)!,\n        nftSerialNumbers: tokenIdToSerialNumbers.get(token.token_id)\n      }\n    });\n  }\n\n  async getAccountInfo(accountId: AccountId) {\n    const accountInfo = await fetch(`${this.url}\/api\/v1\/accounts\/${accountId}`, { method: \"GET\" });\n    const accountInfoJson = await accountInfo.json();\n    return accountInfoJson;\n  }\n\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Next, we will utilize these functions to populate our drop-down menu with the retrieved token data.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Create\u00a0the Available Token Drop-Down Menu<\/h4>\n<p>In this next section, we will dive into the <span class=\"codeInline&gt;src\/pages\/Home.tsx&lt;span&gt; file that is included in the template.&lt;\/p&gt; &lt;p&gt;Our goal is to update the &lt;span class=\" codeinline\"=\"\">Home.tsx<\/span> file and utilize the necessary functions to populate a drop-down menu with the available token information of the connected account. The template provides a wallet interface that handles the supported multiple wallets and is already integrated into the project, simplifying the development process.<\/p>\n<p class=\"inline-p\">Replace the existing code in<\/p>\n<p class=\"codeInline\">src\/pages\/Home.tsx<\/p>\n<p class=\"inline-p\">with the following code:<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">import { MenuItem, TextField, Typography } from \"@mui\/material\";\nimport { Stack } from \"@mui\/system\";\nimport { useWalletInterface } from \"..\/services\/wallets\/useWalletInterface\";\nimport { useEffect, useState } from \"react\";\nimport { AccountId } from \"@hashgraph\/sdk\";\nimport { MirrorNodeAccountTokenBalanceWithInfo, MirrorNodeClient } from \"..\/services\/wallets\/mirrorNodeClient\";\nimport { appConfig } from \"..\/config\";\n\nconst UNSELECTED_SERIAL_NUMBER = -1;\n\nexport default function Home() {\n  const { walletInterface, accountId } = useWalletInterface();\n  const [amount, setAmount] = useState<number>(0);\n  \/\/ include all of this necessary for dropdown\n  const [availableTokens, setAvailableTokens] = useState<MirrorNodeAccountTokenBalanceWithInfo[]>([]);\n  const [selectedTokenId, setSelectedTokenId] = useState<string>('');\n  const [serialNumber, setSerialNumber] = useState<number>(UNSELECTED_SERIAL_NUMBER);\n\n\n  \/\/ include all of this necessary for dropdown\n  \/\/ Purpose: Get the account token balances with token info for the current account and set them to state\n  useEffect(() => {\n    if (accountId === null) {\n      return;\n    }\n    const mirrorNodeClient = new MirrorNodeClient(appConfig.networks.testnet);\n    \/\/ Get token balance with token info for the current account\n    mirrorNodeClient.getAccountTokenBalancesWithTokenInfo(AccountId.fromString(accountId)).then((tokens) => {\n      \/\/ set to state\n      setAvailableTokens(tokens);\n      console.log(tokens);\n    }).catch((error) => {\n      console.error(error);\n    });\n  }, [accountId])\n\n  \/\/ include all of this necessary for dropdown\n  \/\/ Filter out tokens with a balance of 0\n  const tokensWithNonZeroBalance = availableTokens.filter((token) => token.balance > 0);\n  \/\/ include all of this necessary for dropdown\n  \/\/ Get the selected token balance with info\n  const selectedTokenBalanceWithInfo = availableTokens.find((token) => token.token_id === selectedTokenId);\n\n  \/\/ include all of this necessary for dropdown\n  \/\/ reset amount and serial number when token id changes\n  useEffect(() => {\n    setAmount(0);\n    setSerialNumber(UNSELECTED_SERIAL_NUMBER);\n  }, [selectedTokenId]);\n\n  return (\n    <Stack alignItems=\"center\" spacing={4}>\n      <Typography\n        variant=\"h4\"\n        color=\"white\"\n      >\n        Let's buidl a dApp on Hedera\n      <\/Typography>\n      {walletInterface !== null && (\n        <>\n          <Stack\n            direction='row'\n            gap={2}\n            alignItems='center'\n          >\n            <Typography>\n              Transfer\n            <\/Typography>\n            <TextField\n              label='Available Tokens'\n              value={selectedTokenId}\n              select\n              onChange={(e) => setSelectedTokenId(e.target.value)}\n              sx={{\n                width: '250px',\n                height: '50px',\n              }}\n            >\n              <MenuItem\n                value={''}\n              >\n                Select a token\n              <\/MenuItem>\n              {tokensWithNonZeroBalance.map((token) => {\n                const tokenBalanceAdjustedForDecimals = token.balance \/ Math.pow(10, Number.parseInt(token.info.decimals));\n                return (\n                  <MenuItem\n                    key={token.token_id}\n                    value={token.token_id}\n                  >\n                    {token.info.name}({token.token_id}): ({tokenBalanceAdjustedForDecimals})\n                  <\/MenuItem>\n                );\n              }\n              )}\n            <\/TextField>\n            {selectedTokenBalanceWithInfo?.info?.type === \"NON_FUNGIBLE_UNIQUE\" && (\n              <TextField\n                label='Serial Number'\n                select\n                value={serialNumber.toString()}\n                onChange={(e) => setSerialNumber(Number.parseInt(e.target.value))}\n                sx={{\n                  width: '190px',\n                  height: '50px',\n                }}\n              >\n                <MenuItem\n                  value={UNSELECTED_SERIAL_NUMBER}\n                >\n                  Select a Serial Number\n                <\/MenuItem>\n                {selectedTokenBalanceWithInfo.nftSerialNumbers?.map((serialNumber) => {\n                  return (\n                    <MenuItem\n                      key={serialNumber}\n                      value={serialNumber}\n                    >\n                      {serialNumber}\n                    <\/MenuItem>\n                  );\n                }\n                )}\n              <\/TextField>\n            )}\n            {selectedTokenBalanceWithInfo?.info?.type === \"FUNGIBLE_COMMON\" && (\n              <TextField\n                type='number'\n                label='amount'\n                value={amount}\n                onChange={(e) => setAmount(parseInt(e.target.value))}\n                sx={{\n                  maxWidth: '100px'\n                }}\n              \/>\n            )}\n          <\/Stack>\n        <\/>\n      )}\n    <\/Stack>\n  )\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\">The crucial part of the code is found within the <\/p>\n<p class=\"codeInline\">useEffect()<\/p>\n<p class=\"inline-p\"> hook. In this section, we invoke the <\/p>\n<p class=\"codeInline\">getAccountTokenBalanceswithTokenInfo()<\/p>\n<p class=\"inline-p\"> function and update the state variable <\/p>\n<p class=\"codeInline\">availableTokens<\/p>\n<p class=\"inline-p\"> with the returned data. We then apply a filter to remove tokens with a balance of 0 from the <\/p>\n<p class=\"codeInline\">availableTokens<\/p>\n<p class=\"inline-p\"> array.<\/p>\n<\/p>\n<p class=\"inline-p\">Within the React code, we introduced a <\/p>\n<p class=\"codeInline\">TextField<\/p>\n<p class=\"inline-p\"> component with a select attribute to create a drop-down menu. We use the filtered <\/p>\n<p class=\"codeInline\">availableTokens<\/p>\n<p class=\"inline-p\"> to populate the drop-down options. Depending on whether we select an FT or an NFT, we dynamically render either a <\/p>\n<p class=\"codeInline\">TextField<\/p>\n<p class=\"inline-p\"> of type number or a drop-down menu displaying the available serial numbers, respectively.<\/p>\n<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Create Sender\/Receiver Accounts and Start the Project<\/h4>\n<p>To continue with the rest of this tutorial, we need to create sender and Receiver accounts that will be used for the upcoming steps. You will leverage the following <a href=\"https:\/\/github.com\/hedera-dev\/hedera-create-account-and-token-helper\" target=\"_blank\">repository<\/a> to create these accounts. While we will primarily focus on completing the tutorial using the MetaMask wallet, feel free to explore the option of using HashPack or Blade as well. This flexibility ensures you can continue the tutorial using the wallet that best suits your preferences.<\/p>\n<p>To proceed, follow these steps:<\/p>\n<ol>\n<li>Create\u00a0a new directory and change into that directory.<\/li>\n<li>Create a new file named .env in the directory with the following fields:<\/li>\n<\/ol>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">MY_ACCOUNT_ID=<enter your ed25519 account id>\nMY_PRIVATE_KEY=<enter your ed25519 DER private key>\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>3. Execute the following command in that directory<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">npx github:\/hedera-dev\/hedera-create-account-and-token-helper\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p><strong>Note: Private Keys should never be shared publicly.<\/strong><\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>You will see an output similar to the following:<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/account-output.png\" alt=\"\n\n<p>Sample Output<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>Sample Output<\/p>\n<\/figcaption><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Keep this terminal open for the remainder of the tutorial, as you will refer back to it.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Next, import the ECDSA Sender and ECDSA Receiver accounts into MetaMask using their respective private keys.\u00a0<\/p>\n<p>Once both accounts are successfully imported, you can start the DApp by executing the following command:<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">npm run start\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>This will start the DApp on port 3000.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p><strong><em>Note: To connect to Blade, it is necessary to use HTTPS. The provided template already includes HTTPS support. When starting the DApp, you will encounter a Privacy error in the browser about your connection not being private due to not having a valid SSL certificate. To proceed, click the &#8216;Advanced&#8217; option and then select &#8216;Proceed to localhost.&#8217;<\/em><\/strong><\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/browser-warning.png\" alt=\"\n\n<p>Connection is not Private Browser Warning<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>Connection is not Private Browser Warning<\/p>\n<\/figcaption><\/figure>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/connectWallet.png\" alt=\"\n\n<p>DApp Homepage<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>DApp Homepage<\/p>\n<\/figcaption><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Connect to DApp as the Sender<\/h4>\n<p class=\"inline-p\">The template provides the code to transfer FTs and NFTs to a specific account ID or EVM address. You can find the implementation specific to MetaMask at <\/p>\n<p class=\"codeInline\">src\/services\/wallets\/metamask\/metamaskClient.tsx<\/p>\n<p>.<\/p>\n<\/p>\n<p class=\"inline-p\">Moving forward with the tutorial, click the \u2018Connect Wallet\u2019 button and select MetaMask to connect with the Sender.<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Screenshot-2023-06-22-at-7.24.22-PM.png\" alt=\"\n\n<p>Choose your wallet<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>Choose your wallet<\/p>\n<\/figcaption><\/figure>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/connectWithMetaMask_2023-06-22-225747_ppzu.png\" alt=\"\n\n<p>Select the Sender Account<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>Select the Sender Account<\/p>\n<\/figcaption><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>After a successful connection, you will see the following screen:<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/dropdownOfAvailableTokens_2023-06-22-225957_daqc.png\" alt=\"\n\n<p>Sender&#8217;s Available Tokens<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>Sender&#8217;s Available Tokens<\/p>\n<\/figcaption><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Before we transfer, implement a function that verifies whether the Receiver account is associated with the token we intend to transfer. If the receiver is not associated with the token, then the transfer will fail. Needing to associate with a token before receiving it prevents a user from receiving unwanted tokens.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\">In <\/p>\n<p class=\"codeInline\">src\/services\/mirrorNodeClient.ts<\/p>\n<p class=\"inline-p\"> add the following code:<\/p>\n<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">\/\/ Purpose: check if an account is associated with a token\n\/\/ Returns: true if the account is associated with the token, false otherwise\nasync isAssociated(accountId: AccountId, tokenId: string) {\n  const accountTokenBalance = await this.getAccountTokenBalances(accountId);\n  return accountTokenBalance.some(token => token.token_id === tokenId);\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\">Let\u2019s attempt to send the token to the Receiver account. We need to add a Send button to our <\/p>\n<p class=\"codeInline\">Home.tsx<\/p>\n<p class=\"inline-p\"> component. Replace the existing code in <\/p>\n<p class=\"codeInline\">src\/pages\/Home.tsx<\/p>\n<p class=\"inline-p\">with the following code:<\/p>\n<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">import { Button, MenuItem, TextField, Typography } from \"@mui\/material\";\nimport { Stack } from \"@mui\/system\";\nimport { useWalletInterface } from \"..\/services\/wallets\/useWalletInterface\";\nimport SendIcon from '@mui\/icons-material\/Send';\nimport { useEffect, useState } from \"react\";\nimport { AccountId, TokenId } from \"@hashgraph\/sdk\";\nimport { MirrorNodeAccountTokenBalanceWithInfo, MirrorNodeClient } from \"..\/services\/wallets\/mirrorNodeClient\";\nimport { appConfig } from \"..\/config\";\n\nconst UNSELECTED_SERIAL_NUMBER = -1;\n\nexport default function Home() {\n  const { walletInterface, accountId } = useWalletInterface();\n  const [toAccountId, setToAccountId] = useState(\"\");\n  const [amount, setAmount] = useState<number>(0);\n  const [availableTokens, setAvailableTokens] = useState<MirrorNodeAccountTokenBalanceWithInfo[]>([]);\n  const [selectedTokenId, setSelectedTokenId] = useState<string>('');\n  const [serialNumber, setSerialNumber] = useState<number>(UNSELECTED_SERIAL_NUMBER);\n\n  const [tokenIdToAssociate, setTokenIdToAssociate] = useState(\"\");\n\n  \/\/ Purpose: Get the account token balances with token info for the current account and set them to state\n  useEffect(() => {\n    if (accountId === null) {\n      return;\n    }\n    const mirrorNodeClient = new MirrorNodeClient(appConfig.networks.testnet);\n    \/\/ Get token balance with token info for the current account\n    mirrorNodeClient.getAccountTokenBalancesWithTokenInfo(AccountId.fromString(accountId)).then((tokens) => {\n      \/\/ set to state\n      setAvailableTokens(tokens);\n      console.log(tokens);\n    }).catch((error) => {\n      console.error(error);\n    });\n  }, [accountId])\n\n\n  \/\/ Filter out tokens with a balance of 0\n  const tokensWithNonZeroBalance = availableTokens.filter((token) => token.balance > 0);\n  \/\/ include all of this necessary for dropdown\n  \/\/ Get the selected token balance with info\n  const selectedTokenBalanceWithInfo = availableTokens.find((token) => token.token_id === selectedTokenId);\n\n  \/\/ reset amount and serial number when token id changes\n  useEffect(() => {\n    setAmount(0);\n    setSerialNumber(UNSELECTED_SERIAL_NUMBER);\n  }, [selectedTokenId]);\n\n  return (\n    <Stack alignItems=\"center\" spacing={4}>\n      <Typography\n        variant=\"h4\"\n        color=\"white\"\n      >\n        Let's buidl a dApp on Hedera\n      <\/Typography>\n      {walletInterface !== null && (\n        <>\n          <Stack\n            direction='row'\n            gap={2}\n            alignItems='center'\n          >\n            <Typography>\n              Transfer\n            <\/Typography>\n            <TextField\n              label='Available Tokens'\n              value={selectedTokenId}\n              select\n              onChange={(e) => setSelectedTokenId(e.target.value)}\n              sx={{\n                width: '250px',\n                height: '50px',\n              }}\n            >\n              <MenuItem\n                value={''}\n              >\n                Select a token\n              <\/MenuItem>\n              {tokensWithNonZeroBalance.map((token) => {\n                const tokenBalanceAdjustedForDecimals = token.balance \/ Math.pow(10, Number.parseInt(token.info.decimals));\n                return (\n                  <MenuItem\n                    key={token.token_id}\n                    value={token.token_id}\n                  >\n                    {token.info.name}({token.token_id}): ({tokenBalanceAdjustedForDecimals})\n                  <\/MenuItem>\n                );\n              }\n              )}\n            <\/TextField>\n            {selectedTokenBalanceWithInfo?.info?.type === \"NON_FUNGIBLE_UNIQUE\" && (\n              <TextField\n                label='Serial Number'\n                select\n                value={serialNumber.toString()}\n                onChange={(e) => setSerialNumber(Number.parseInt(e.target.value))}\n                sx={{\n                  width: '190px',\n                  height: '50px',\n                }}\n              >\n                <MenuItem\n                  value={UNSELECTED_SERIAL_NUMBER}\n                >\n                  Select a Serial Number\n                <\/MenuItem>\n                {selectedTokenBalanceWithInfo.nftSerialNumbers?.map((serialNumber) => {\n                  return (\n                    <MenuItem\n                      key={serialNumber}\n                      value={serialNumber}\n                    >\n                      {serialNumber}\n                    <\/MenuItem>\n                  );\n                }\n                )}\n              <\/TextField>\n            )}\n            {selectedTokenBalanceWithInfo?.info?.type === \"FUNGIBLE_COMMON\" && (\n              <TextField\n                type='number'\n                label='amount'\n                value={amount}\n                onChange={(e) => setAmount(parseInt(e.target.value))}\n                sx={{\n                  maxWidth: '100px'\n                }}\n              \/>\n            )}\n            <Typography>\n              HTS Token\n              to\n            <\/Typography>\n            <TextField\n              value={toAccountId}\n              onChange={(e) => setToAccountId(e.target.value)}\n              label='account id or evm address'\n            \/>\n            <Button\n              variant='contained'\n              onClick={async () => {\n                if (selectedTokenBalanceWithInfo === undefined) {\n                  console.log(`Token Id is empty.`)\n                  return;\n                }\n                \n                \/\/ check if receiver has associated\n                const mirrorNodeClient = new MirrorNodeClient(appConfig.networks.testnet);\n                const isAssociated = await mirrorNodeClient.isAssociated(AccountId.fromString(toAccountId), selectedTokenId);\n                if (!isAssociated) {\n                  console.log(`Receiver is not associated with token id: ${selectedTokenId}`);\n                  return;\n                }\n                if (selectedTokenBalanceWithInfo.info.type === \"NON_FUNGIBLE_UNIQUE\") {\n                  await walletInterface.transferNonFungibleToken(\n                    AccountId.fromString(toAccountId),\n                    TokenId.fromString(selectedTokenId),\n                    serialNumber);\n                } else {\n                  const amountWithDecimals = amount * Math.pow(10, Number.parseInt(selectedTokenBalanceWithInfo.info.decimals));\n                  await walletInterface.transferFungibleToken(\n                    AccountId.fromString(toAccountId),\n                    TokenId.fromString(selectedTokenId),\n                    amountWithDecimals);\n                }\n              }}\n            >\n              <SendIcon \/>\n            <\/Button>\n          <\/Stack>\n        <\/>\n      )}\n    <\/Stack>\n  )\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\">There are two crucial points in the new code we added. First, within the <\/p>\n<p class=\"codeInline\">&lt;Button&gt;<\/p>\n<p class=\"inline-p\"> component&#8217;s <\/p>\n<p class=\"codeInline\">onClick<\/p>\n<p class=\"inline-p\"> event, we invoke the <\/p>\n<p class=\"codeInline\">isAssociated()<\/p>\n<p class=\"inline-p\"> function and return early if it returns false. This check ensures that the Receiver account has been associated with the token.\u00a0<\/p>\n<p class=\"inline-p\">The second important part is the formula used to account for token decimals, which is as follows:<\/p>\n<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">const amountWithDecimals = amount * Math.pow(10, Number.parseInt(selectedTokenBalanceWithInfo.info.decimals));\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>In the case of FTs, they often have a decimal representation to denote the token&#8217;s smallest unit. For example, consider an FT with a decimal value of 2. In this case, if we have an amount of 10, the formula will convert it to 1000 (10 * 10^2) before transferring the tokens. This adjustment is necessary to ensure accurate value representation and compatibility with the token&#8217;s decimal system.<\/p>\n<p>Now that we added our necessary components to transfer head over to your browser to see the updated user interface (UI).<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/image7_2023-06-22-223931_takd.png\" alt=\"\"\/><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Open the inspector tool in your browser and navigate to the console section. Then, copy the ECDSA Receiver account ID. Paste the account ID into the provided text box and select the FT with an amount of\u00a01 to transfer.<\/p>\n<p>Finally, click the Send button. Take note of the message displayed indicating that the receiver is not associated with the provided token ID.<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/notAssociatedMessage.png\" alt=\"\n\n<p>Receiver is not Associated<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>Receiver is not Associated<\/p>\n<\/figcaption><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Associate As the Receiver<\/h4>\n<p class=\"inline-p\">To enable the Receiver account to receive an HTS token, it must be associated with the respective token. This association process is facilitated by the <\/p>\n<p class=\"codeInline\">associateToken()<\/p>\n<p class=\"inline-p\"> method found in the <\/p>\n<p class=\"codeInline\">metamaskClient.tsx<\/p>\n<p class=\"inline-p\"> file located in the <\/p>\n<p class=\"codeInline\">src\/services\/wallets\/metamask<\/p>\n<p class=\"inline-p\"> directory.<\/p>\n<\/p>\n<p class=\"inline-p\">The <\/p>\n<p class=\"codeInline\">associateToken()<\/p>\n<p class=\"inline-p\"> method accepts a <\/p>\n<p class=\"codeInline\">TokenId<\/p>\n<p class=\"inline-p\"> as a parameter and converts it into a <\/p>\n<p class=\"codeInline\">ContractId<\/p>\n<p class=\"inline-p\">, allowing you to call <\/p>\n<p class=\"codeInline\">associate<\/p>\n<p class=\"inline-p\"> on the token. This functionality highlights the capability of treating HTS tokens in a similar manner to ERC-20 and ERC-721 tokens, made possible by <a href=\"https:\/\/hips.hedera.com\/hip\/hip-218\">HIP-218<\/a>. Associating is a unique Hedera functionality and <a href=\"https:\/\/hips.hedera.com\/hip\/hip-719\">HIP-719<\/a> extended the previous functionality of treating HTS ERC tokens to both associate and dissociate functions.<\/p>\n<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">async associateToken(tokenId: TokenId) {\n  \/\/ send the transaction\n  \/\/ convert tokenId to contract id\n  const hash = await this.executeContractFunction(\n    ContractId.fromString(tokenId.toString()),\n    'associate',\n    new ContractFunctionParameterBuilder(),\n    appConfig.constants.METAMASK_GAS_LIMIT_ASSOCIATE\n  );\n\n  return hash;\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>We must have the Receiver account associated with the NFT token ID. Let\u2019s continue by disconnecting from the DApp with the current account. You disconnect through the MetaMask extension.<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/disconnectMetaMask.png\" alt=\"\"\/><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Connect as the Receiver account.\u00a0<\/p>\n<p>Once connected, your DApp will update, and the drop-down menu will show that the receiver has no available tokens to transfer.<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/image14_2023-06-22-224504_hrrq.png\" alt=\"\"\/><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\">Let\u2019s add the necessary UI components so we can associate. Replace the existing code in <\/p>\n<p class=\"codeInline\">src\/pages\/Home.tsx<\/p>\n<p class=\"inline-p\"> with the following code:<\/p>\n<\/p>\n<\/div>\n<div class=\"hedera-code-window\" style=\"background-image:url('https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg');padding:24px;border-radius:8px;margin:24px 0;\">\n<p>  <!-- Hidden image so WP All Import downloads this background image into Media Library --><br \/>\n  <img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/CodeSnippetBackground-scaled.jpg\" alt=\"code window background\" style=\"display:none;\" \/><\/p>\n<div class=\"code-window-header\">\n<div class=\"code-window-title\"><\/div>\n<div class=\"code-window-body\"><\/div>\n<\/p><\/div>\n<pre><code class=\"language-javascript\">import { Button, MenuItem, TextField, Typography } from \"@mui\/material\";\nimport { Stack } from \"@mui\/system\";\nimport { useWalletInterface } from \"..\/services\/wallets\/useWalletInterface\";\nimport SendIcon from '@mui\/icons-material\/Send';\nimport { useEffect, useState } from \"react\";\nimport { AccountId, TokenId } from \"@hashgraph\/sdk\";\nimport { MirrorNodeAccountTokenBalanceWithInfo, MirrorNodeClient } from \"..\/services\/wallets\/mirrorNodeClient\";\nimport { appConfig } from \"..\/config\";\n\nconst UNSELECTED_SERIAL_NUMBER = -1;\n\nexport default function Home() {\n  const { walletInterface, accountId } = useWalletInterface();\n  const [toAccountId, setToAccountId] = useState(\"\");\n  const [amount, setAmount] = useState<number>(0);\n  \/\/ include all of this necessary for dropdown\n  const [availableTokens, setAvailableTokens] = useState<MirrorNodeAccountTokenBalanceWithInfo[]>([]);\n  const [selectedTokenId, setSelectedTokenId] = useState<string>('');\n  const [serialNumber, setSerialNumber] = useState<number>(UNSELECTED_SERIAL_NUMBER);\n\n  const [tokenIdToAssociate, setTokenIdToAssociate] = useState(\"\");\n\n  \/\/ include all of this necessary for dropdown\n  \/\/ Purpose: Get the account token balances with token info for the current account and set them to state\n  useEffect(() => {\n    if (accountId === null) {\n      return;\n    }\n    const mirrorNodeClient = new MirrorNodeClient(appConfig.networks.testnet);\n    \/\/ Get token balance with token info for the current account\n    mirrorNodeClient.getAccountTokenBalancesWithTokenInfo(AccountId.fromString(accountId)).then((tokens) => {\n      \/\/ set to state\n      setAvailableTokens(tokens);\n      console.log(tokens);\n    }).catch((error) => {\n      console.error(error);\n    });\n  }, [accountId])\n\n  \/\/ include all of this necessary for dropdown\n  \/\/ Filter out tokens with a balance of 0\n  const tokensWithNonZeroBalance = availableTokens.filter((token) => token.balance > 0);\n  \/\/ include all of this necessary for dropdown\n  \/\/ Get the selected token balance with info\n  const selectedTokenBalanceWithInfo = availableTokens.find((token) => token.token_id === selectedTokenId);\n\n  \/\/ include all of this necessary for dropdown\n  \/\/ reset amount and serial number when token id changes\n  useEffect(() => {\n    setAmount(0);\n    setSerialNumber(UNSELECTED_SERIAL_NUMBER);\n  }, [selectedTokenId]);\n\n  return (\n    <Stack alignItems=\"center\" spacing={4}>\n      <Typography\n        variant=\"h4\"\n        color=\"white\"\n      >\n        Let's buidl a dApp on Hedera\n      <\/Typography>\n      {walletInterface !== null && (\n        <>\n          <Stack\n            direction='row'\n            gap={2}\n            alignItems='center'\n          >\n            <Typography>\n              Transfer\n            <\/Typography>\n            <TextField\n              label='Available Tokens'\n              value={selectedTokenId}\n              select\n              onChange={(e) => setSelectedTokenId(e.target.value)}\n              sx={{\n                width: '250px',\n                height: '50px',\n              }}\n            >\n              <MenuItem\n                value={''}\n              >\n                Select a token\n              <\/MenuItem>\n              {tokensWithNonZeroBalance.map((token) => {\n                const tokenBalanceAdjustedForDecimals = token.balance \/ Math.pow(10, Number.parseInt(token.info.decimals));\n                return (\n                  <MenuItem\n                    key={token.token_id}\n                    value={token.token_id}\n                  >\n                    {token.info.name}({token.token_id}): ({tokenBalanceAdjustedForDecimals})\n                  <\/MenuItem>\n                );\n              }\n              )}\n            <\/TextField>\n            {selectedTokenBalanceWithInfo?.info?.type === \"NON_FUNGIBLE_UNIQUE\" && (\n              <TextField\n                label='Serial Number'\n                select\n                value={serialNumber.toString()}\n                onChange={(e) => setSerialNumber(Number.parseInt(e.target.value))}\n                sx={{\n                  width: '190px',\n                  height: '50px',\n                }}\n              >\n                <MenuItem\n                  value={UNSELECTED_SERIAL_NUMBER}\n                >\n                  Select a Serial Number\n                <\/MenuItem>\n                {selectedTokenBalanceWithInfo.nftSerialNumbers?.map((serialNumber) => {\n                  return (\n                    <MenuItem\n                      key={serialNumber}\n                      value={serialNumber}\n                    >\n                      {serialNumber}\n                    <\/MenuItem>\n                  );\n                }\n                )}\n              <\/TextField>\n            )}\n            {selectedTokenBalanceWithInfo?.info?.type === \"FUNGIBLE_COMMON\" && (\n              <TextField\n                type='number'\n                label='amount'\n                value={amount}\n                onChange={(e) => setAmount(parseInt(e.target.value))}\n                sx={{\n                  maxWidth: '100px'\n                }}\n              \/>\n            )}\n            {\/* not included in the dropdown stage. this is in the association\/send stage *\/}\n            <Typography>\n              HTS Token\n              to\n            <\/Typography>\n            <TextField\n              value={toAccountId}\n              onChange={(e) => setToAccountId(e.target.value)}\n              label='account id or evm address'\n            \/>\n            <Button\n              variant='contained'\n              onClick={async () => {\n                if (selectedTokenBalanceWithInfo === undefined) {\n                  console.log(`Token Id is empty.`)\n                  return;\n                }\n                \n                \/\/ check if receiver has associated\n                const mirrorNodeClient = new MirrorNodeClient(appConfig.networks.testnet);\n                const isAssociated = await mirrorNodeClient.isAssociated(AccountId.fromString(toAccountId), selectedTokenId);\n                if (!isAssociated) {\n                  console.log(`Receiver is not associated with token id: ${selectedTokenId}`);\n                  return;\n                }\n                if (selectedTokenBalanceWithInfo.info.type === \"NON_FUNGIBLE_UNIQUE\") {\n                  await walletInterface.transferNonFungibleToken(\n                    AccountId.fromString(toAccountId),\n                    TokenId.fromString(selectedTokenId),\n                    serialNumber);\n                } else {\n                  const amountWithDecimals = amount * Math.pow(10, Number.parseInt(selectedTokenBalanceWithInfo.info.decimals));\n                  await walletInterface.transferFungibleToken(\n                    AccountId.fromString(toAccountId),\n                    TokenId.fromString(selectedTokenId),\n                    amountWithDecimals);\n                }\n              }}\n            >\n              <SendIcon \/>\n            <\/Button>\n          <\/Stack>\n          <Stack\n            direction='row'\n            gap={2}\n            alignItems='center'\n          >\n            <TextField\n              value={tokenIdToAssociate}\n              label='token id'\n              onChange={(e) => setTokenIdToAssociate(e.target.value)}\n            \/>\n            <Button\n              variant='contained'\n              onClick={async () => {\n                if (tokenIdToAssociate === \"\") {\n                  console.log(`Token Id is empty.`)\n                  return;\n                }\n                await walletInterface.associateToken(TokenId.fromString(tokenIdToAssociate));\n              }}\n            >\n              Associate Token\n            <\/Button>\n          <\/Stack>\n        <\/>\n      )}\n    <\/Stack>\n  )\n}\n<\/code><\/pre>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>After adding the code, you will notice that the UI updates to display a text box and a button specifically for the association process.<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/image20.png\" alt=\"\n\n<p>Associate Button Has Been Added<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>Associate Button Has Been Added<\/p>\n<\/figcaption><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\">To associate the Receiver account with the HTS token, enter the <\/p>\n<p class=\"codeInline\">NFTTokenID<\/p>\n<p class=\"inline-p\"> of the Sender&#8217;s NFT collection in the token ID textbox and click the Associate button. MetaMask will prompt you to sign the transaction. If the extension doesn&#8217;t appear automatically, you may need to open it manually by clicking on the extension.<\/p>\n<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p class=\"inline-p\"><strong><em>Note: The template, by default, uses the <\/em><a href=\"https:\/\/swirldslabs.com\/hashio\/\"><em>Hashio<\/em><\/a><em> JSON RPC Relay URL to work with MetaMask. If you are experiencing degraded performance, I encourage you to follow the steps outlined in this <\/em><a href=\"https:\/\/docs.hedera.com\/hedera\/tutorials\/more-tutorials\/json-rpc-connections\"><em>guide<\/em><\/a><em> to use Arkhia or set up your own local JSON RPC Relay. You can then edit the <\/em><\/strong><\/p>\n<p class=\"codeInline\"><strong><em>src\/config\/networks.ts<\/em><\/strong><\/p>\n<p class=\"inline-p\"><strong><em> with the new JSON RPC Relay URL.<\/em><em><\/em><\/strong><\/p>\n<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Screenshot-2023-06-22-at-3.47.29-PM.png\" alt=\"\n\n<p>src\/config\/network.ts is where you can update the JSON RPC Relay URL<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>src\/config\/network.ts is where you can update the JSON RPC Relay URL<\/p>\n<\/figcaption><\/figure>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/metaMaskAssociate.png\" alt=\"\"\/><\/figure>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/AssociateConfirmed.png\" alt=\"\"\/><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Transfer An NFT as the Sender<br \/><\/h4>\n<p>Once the Associate transaction is confirmed, disconnect from the current session and reconnect as the Sender account.\u00a0<\/p>\n<p>As the Sender, enter the account ID or EVM address of the Receiver account. Select the NFT with serial number 5 from the drop-down menu and click the send button.\u00a0<\/p>\n<p>Sign the transaction on MetaMask, which will then transfer the NFT from the Sender to the receiver account seamlessly.<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/image12.png\" alt=\"\n\n<p>Transfer the NFT with Serial Number 5<\/p>\n<p>&#8220;\/><figcaption class=\"image-caption size--xs\">\n<p>Transfer the NFT with Serial Number 5<\/p>\n<\/figcaption><\/figure>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/MetaMaskTransferFrom.png\" alt=\"\"\/><\/figure>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/sendTokenConfirmed.png\" alt=\"\"\/><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Verify Receiver Received the NFT<\/h4>\n<p>Disconnect as the Sender and reconnect as the Receiver.\u00a0<\/p>\n<p>Check the drop-down menu to ensure the Receiver account has NFT serial number 5.<\/p>\n<\/div>\n<figure class=\"blog-image mb-40\"><img decoding=\"async\" src=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/image15_2023-06-22-233120_ofcl.png\" alt=\"\"\/><\/figure>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Try with HashPack or Blade<\/h4>\n<p>Optionally, you can import the ED25519 Sender\/Receiver\u00a0accounts into HashPack and Blade and associate and transfer NFT\/FT tokens with those additional wallets.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<p>Congratulations! You have successfully walked through creating a Hedera DApp that transfers HTS tokens to MetaMask, HashPack, and Blade.<\/p>\n<\/div>\n<div class=\"body-text BodyCopy mb-40 style-1\">\n<h4 class=\"color-ultraviolet\">Summary<\/h4>\n<p>We embarked on an exciting adventure together, using the CRA Hedera DApp template. Along the way, we learned how to write queries to fetch account token balances, token info, and NFT details from the mirror node. We even created a drop-down menu that shows the available token balances. In addition, we added a textbox and a button to associate accounts with token IDs. It was an incredible accomplishment, and I encourage everyone to keep learning!<\/p>\n<\/p>\n<p>Continue Learning<\/p>\n<ul>\n<li>Try <a href=\"https:\/\/docs.hedera.com\/hedera\/tutorials\">Tutorials<\/a><\/li>\n<li><a href=\"https:\/\/hedera.com\/discord\">Join the Developer Discord<\/a><\/li>\n<li>Explore <a href=\"https:\/\/hedera.com\/learning\">The Hedera Learning Center<\/a><\/li>\n<\/ul>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this step-by-step guide, we&#8217;ll show you how to create a Hedera DApp using React, Material UI, Ethers, and TypeScript. With the help of the Create React App (CRA) Hedera DApp template, you&#8217;ll be able to seamlessly integrate popular wallets like MetaMask, Hashpack, and Blade. You&#8217;ll learn how to query the mirror node and incorporate HTS features, enabling users to effortlessly manage and transact with HTS tokens.<\/p>\n","protected":false},"author":10,"featured_media":16847,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":""},"categories":[1],"tags":[45],"ppma_author":[43],"class_list":["post-15739","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-technical"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.9 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Develop a Hedera DApp with MetaMask, HashPack, and Blade Integration | Hedera<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Develop a Hedera DApp with MetaMask, HashPack, and Blade Integration | Hedera\" \/>\n<meta property=\"og:description\" content=\"In this step-by-step guide, we&#039;ll show you how to create a Hedera DApp using React, Material UI, Ethers, and TypeScript. With the help of the Create React App (CRA) Hedera DApp template, you&#039;ll be able to seamlessly integrate popular wallets like MetaMask, Hashpack, and Blade. You&#039;ll learn how to query the mirror node and incorporate HTS features, enabling users to effortlessly manage and transact with HTS tokens.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/\" \/>\n<meta property=\"og:site_name\" content=\"Hedera\" \/>\n<meta property=\"article:published_time\" content=\"2023-06-27T15:43:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-12-08T18:25:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"670\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Hedera Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/\"},\"author\":{\"name\":\"Hedera Team\",\"@id\":\"https:\/\/hedera.com\/#\/schema\/person\/2dc6146f9f20a44d3de58c834d52e9f4\"},\"headline\":\"Develop a Hedera DApp with MetaMask, HashPack, and Blade Integration\",\"datePublished\":\"2023-06-27T15:43:00+00:00\",\"dateModified\":\"2025-12-08T18:25:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/\"},\"wordCount\":1259,\"publisher\":{\"@id\":\"https:\/\/hedera.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner.png\",\"keywords\":[\"technical\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/\",\"url\":\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/\",\"name\":\"Develop a Hedera DApp with MetaMask, HashPack, and Blade Integration | Hedera\",\"isPartOf\":{\"@id\":\"https:\/\/hedera.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner.png\",\"datePublished\":\"2023-06-27T15:43:00+00:00\",\"dateModified\":\"2025-12-08T18:25:44+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#primaryimage\",\"url\":\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner.png\",\"contentUrl\":\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner.png\",\"width\":1200,\"height\":670},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/hedera.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Develop a Hedera DApp with MetaMask, HashPack, and Blade Integration\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/hedera.com\/#website\",\"url\":\"https:\/\/hedera.com\/\",\"name\":\"Hedera\",\"description\":\"Hello future\",\"publisher\":{\"@id\":\"https:\/\/hedera.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/hedera.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/hedera.com\/#organization\",\"name\":\"Hedera\",\"url\":\"https:\/\/hedera.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/hedera.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/09\/hedera_logo.png\",\"contentUrl\":\"https:\/\/hedera.com\/wp-content\/uploads\/2025\/09\/hedera_logo.png\",\"width\":500,\"height\":375,\"caption\":\"Hedera\"},\"image\":{\"@id\":\"https:\/\/hedera.com\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Develop a Hedera DApp with MetaMask, HashPack, and Blade Integration | Hedera","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/","og_locale":"en_US","og_type":"article","og_title":"Develop a Hedera DApp with MetaMask, HashPack, and Blade Integration | Hedera","og_description":"In this step-by-step guide, we'll show you how to create a Hedera DApp using React, Material UI, Ethers, and TypeScript. With the help of the Create React App (CRA) Hedera DApp template, you'll be able to seamlessly integrate popular wallets like MetaMask, Hashpack, and Blade. You'll learn how to query the mirror node and incorporate HTS features, enabling users to effortlessly manage and transact with HTS tokens.","og_url":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/","og_site_name":"Hedera","article_published_time":"2023-06-27T15:43:00+00:00","article_modified_time":"2025-12-08T18:25:44+00:00","og_image":[{"width":1200,"height":670,"url":"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner.png","type":"image\/png"}],"author":"Hedera Team","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#article","isPartOf":{"@id":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/"},"author":{"name":"Hedera Team","@id":"https:\/\/hedera.com\/#\/schema\/person\/2dc6146f9f20a44d3de58c834d52e9f4"},"headline":"Develop a Hedera DApp with MetaMask, HashPack, and Blade Integration","datePublished":"2023-06-27T15:43:00+00:00","dateModified":"2025-12-08T18:25:44+00:00","mainEntityOfPage":{"@id":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/"},"wordCount":1259,"publisher":{"@id":"https:\/\/hedera.com\/#organization"},"image":{"@id":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#primaryimage"},"thumbnailUrl":"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner.png","keywords":["technical"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/","url":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/","name":"Develop a Hedera DApp with MetaMask, HashPack, and Blade Integration | Hedera","isPartOf":{"@id":"https:\/\/hedera.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#primaryimage"},"image":{"@id":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#primaryimage"},"thumbnailUrl":"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner.png","datePublished":"2023-06-27T15:43:00+00:00","dateModified":"2025-12-08T18:25:44+00:00","breadcrumb":{"@id":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#primaryimage","url":"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner.png","contentUrl":"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner.png","width":1200,"height":670},{"@type":"BreadcrumbList","@id":"https:\/\/hedera.com\/blog\/develop-a-hedera-dapp-with-metamask-hashpack-and-blade-integration\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/hedera.com\/"},{"@type":"ListItem","position":2,"name":"Develop a Hedera DApp with MetaMask, HashPack, and Blade Integration"}]},{"@type":"WebSite","@id":"https:\/\/hedera.com\/#website","url":"https:\/\/hedera.com\/","name":"Hedera","description":"Hello future","publisher":{"@id":"https:\/\/hedera.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/hedera.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/hedera.com\/#organization","name":"Hedera","url":"https:\/\/hedera.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/hedera.com\/#\/schema\/logo\/image\/","url":"https:\/\/hedera.com\/wp-content\/uploads\/2025\/09\/hedera_logo.png","contentUrl":"https:\/\/hedera.com\/wp-content\/uploads\/2025\/09\/hedera_logo.png","width":500,"height":375,"caption":"Hedera"},"image":{"@id":"https:\/\/hedera.com\/#\/schema\/logo\/image\/"}}]}},"featured_image_src":"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner-600x400.png","featured_image_src_square":"https:\/\/hedera.com\/wp-content\/uploads\/2025\/12\/Develop-a-Hedera-Dapp-Blog-Banner-600x600.png","author_info":{"display_name":"Hedera Team","author_link":"https:\/\/hedera.com\/blog\/author\/hedera-team\/"},"authors":[{"term_id":43,"user_id":10,"is_guest":0,"slug":"hedera-team","display_name":"Hedera Team","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/7ed01931dc9498365746508c4ca49ed0507ef65e04e0b82ffe88c50ef9242b1d?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":""}],"_links":{"self":[{"href":"https:\/\/hedera.com\/wp-json\/wp\/v2\/posts\/15739","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hedera.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hedera.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hedera.com\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/hedera.com\/wp-json\/wp\/v2\/comments?post=15739"}],"version-history":[{"count":0,"href":"https:\/\/hedera.com\/wp-json\/wp\/v2\/posts\/15739\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hedera.com\/wp-json\/wp\/v2\/media\/16847"}],"wp:attachment":[{"href":"https:\/\/hedera.com\/wp-json\/wp\/v2\/media?parent=15739"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hedera.com\/wp-json\/wp\/v2\/categories?post=15739"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hedera.com\/wp-json\/wp\/v2\/tags?post=15739"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/hedera.com\/wp-json\/wp\/v2\/ppma_author?post=15739"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}