
{"id":49763,"date":"2025-03-05T11:27:38","date_gmt":"2025-03-05T11:27:38","guid":{"rendered":"https:\/\/mycryptomania.com\/?p=49763"},"modified":"2025-03-05T11:27:38","modified_gmt":"2025-03-05T11:27:38","slug":"guideline-to-be-qa-web3-complete-e2e-defi-project-with-synpress-playwright-and-hardhat-anvil","status":"publish","type":"post","link":"https:\/\/mycryptomania.com\/?p=49763","title":{"rendered":"Guideline to be QA Web3: Complete E2E DeFi Project with Synpress (Playwright) and Hardhat\/Anvil"},"content":{"rendered":"<p>In my previous blog, <a href=\"https:\/\/medium.com\/coinmonks\/qa-blockchain-testing-smart-contract-network-performance-with-hardhat-d01e99e331e7\"><em>QA Blockchain Testing: Smart Contract &amp; Network Performance with Hardhat<\/em><\/a>, we explored the fundamentals of node testing for smart contracts. Today, we\u2019re taking the next step by diving into comprehensive testing for Web3 decentralized applications (DApps).<\/p>\n<p>Blockchain testing presents unique challenges for QA professionals. Many struggle with three key obstacles: limited practical experience with blockchain technology and business logic, a scarcity of specialized testing tools, and difficulty designing effective test cases for immutable, public transactions that directly involve financial assets.<\/p>\n<p>To address these challenges, I\u2019ve created a comprehensive learning project that allows QA testers to practice end-to-end testing on their own localhost environment. This approach eliminates the restrictions of public testnets, where free tokens are often limited by daily faucet allowances.<\/p>\n<p>I\u2019ll share the complete GitHub repository at the end of this blog as a resource for the QA community to enhance their blockchain testing\u00a0skills.<\/p>\n<h3>Table of Contents:<\/h3>\n<p><a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#1799\">Essential Knowledge for Web3\u00a0QA<\/a><a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#b217\">Understanding DeFi Lending Protocols<\/a><a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#91c5\">How to Test End-to-End DeFi Applications<\/a><a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#ff1f\">Synpress and MetaMask Integration with Playwright<\/a><a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#9981\">Using Anvil for Network Simulation<\/a><a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#1a9e\">Testing Across Layer 1 and Layer 2\u00a0Networks<\/a><\/p>\n<h3>Essential Knowledge for Web3\u00a0QA<\/h3>\n<h4>1. Blockchain Fundamentals<\/h4>\n<p><strong>Core Concepts:<\/strong><\/p>\n<p><strong>Transactions and Gas<\/strong>: Understand how transactions work, gas fees, and transaction finality<strong>Wallets and Accounts<\/strong>: Know how private\/public keys work and how wallets connect to\u00a0dApps<strong>Smart Contracts<\/strong>: Understand basic smart contract functionality and limitations<strong>Consensus Mechanisms<\/strong>: Basic understanding of Proof of Work vs. Proof of\u00a0Stake<strong>Networks and Forks<\/strong>: Differentiate between mainnet, testnet, and local development networks<\/p>\n<p><strong>Practical Knowledge:<\/strong><\/p>\n<p>Set up MetaMask and other popular\u00a0walletsExperience making transactions on\u00a0testnetsUse block explorers (Etherscan, Arbiscan, etc.) to verify transactions<\/p>\n<h4>2. Web3 Development Stack<\/h4>\n<p><strong>Familiarity with:<\/strong><\/p>\n<p><strong>Frontend Libraries<\/strong>: React, ethers.js, web3.js,\u00a0wagmi<strong>Development Frameworks<\/strong>: Hardhat, Foundry, Truffle,\u00a0Brownie<strong>Testing Frameworks<\/strong>: Playwright, Cypress, Selenium with MetaMask extensions<strong>Local Blockchain Environments<\/strong>: Anvil, Hardhat Network,\u00a0Ganache<\/p>\n<h4>3. DeFi and Web3 Application Patterns<\/h4>\n<p><strong>Common Patterns:<\/strong><\/p>\n<p><strong>Connect Wallet Flow<\/strong>: Standard wallet connection patterns<strong>Transaction Approval Flow<\/strong>: Understanding approvals vs. transactions<strong>Asynchronous State Updates<\/strong>: How blockchain confirmations affect UI\u00a0updates<strong>Network Switching<\/strong>: How applications handle network\u00a0changes<\/p>\n<h3>Understanding DeFi Lending Protocols<\/h3>\n<p>Lending protocols in smart contracts represent decentralized financial systems that eliminate the need for traditional banks as intermediaries. These protocols operate transparently with clearly defined rules governing borrowing, interest rates, and liquidation processes.<\/p>\n<p>To understand how these protocols work, it\u2019s important to familiarize yourself with these key concepts:<\/p>\n<p><strong>Collateral<\/strong>: Assets deposited by borrowers as security for their loans. This collateral serves as insurance for the protocol, demonstrating that borrowers have sufficient assets to back their borrowed\u00a0funds.<strong>Health Factor<\/strong>: A numerical representation of a borrower\u2019s position safety (risk level). If the collateral value decreases significantly or interest accumulates substantially, the health factor drops, potentially leading to liquidation.<strong>Liquidation<\/strong>: The process triggered when a borrower\u2019s health factor falls below a critical threshold. In this state, the borrower\u2019s collateral can be forcibly sold at a discount (liquidation bonus) to liquidators who help repay the outstanding debt.<strong>Interest Rate<\/strong>: The cost of borrowing assets over time. Borrowers pay interest when they hold borrowed assets for extended periods, while lenders earn this interest as compensation for providing liquidity to the protocol.<\/p>\n<p>The liquidator sees the liquidation status of the borrower and pays part of her debt. As a result, the borrower\u2019s health factor decreases from 0.59 to 0.47, making it easier for them to repay the remaining debt\u00a0later.<\/p>\n<h3>How to Test End-to-End DeFi Applications<\/h3>\n<p>End-to-End testing simulates real user behavior by testing the complete flow of an application from start to finish. In the context of DeFi applications, E2E testing\u00a0means:<\/p>\n<p><strong>Starting with a wallet connection<\/strong>\u200a\u2014\u200ajust like a real user\u00a0would<strong>Performing complete financial transactions<\/strong>\u200a\u2014\u200adeposits, borrows, withdraws, etc.<strong>Verifying results across all layers<\/strong>\u200a\u2014\u200aUI changes, blockchain state, database\u00a0records<strong>Testing entire user journeys<\/strong>\u200a\u2014\u200anot just individual functions<\/p>\n<p>The diagram below illustrates the complex interactions in a DeFi lending protocol during deposit and borrow flows. Understanding these interactions is crucial for designing comprehensive test\u00a0cases:<\/p>\n<p><strong>Borrower flow:<\/strong><\/p>\n<p><strong>Liquidator flow:<\/strong><\/p>\n<p><strong>Core Lending Protocol Functions<\/strong><\/p>\n<p><strong>Deposit<\/strong>: Supply collateral to the\u00a0protocol<strong>Borrow<\/strong>: Take out a loan against your collateral<strong>Repay<\/strong>: Pay back borrowed assets plus\u00a0interest<strong>Withdraw<\/strong>: Remove your collateral from the\u00a0protocol<strong>Liquidate<\/strong>: Repay part of an unhealthy loan in exchange for a discount on the collateral<\/p>\n<p>As you can see, a simple user action like depositing ETH triggers multiple interactions:<\/p>\n<p>Price checks with an oracle\u00a0serviceToken conversions (ETH to\u00a0WETH)Smart contract state\u00a0updatesUser position\u00a0trackingActivity logging in the\u00a0database<\/p>\n<p>Our E2E tests must verify that each of these steps completes successfully, just as they would in a production environment.<\/p>\n<h3>Synpress and MetaMask Integration with Playwright<\/h3>\n<p>You can use the <strong>Synpress<\/strong> framework, an end-to-end (E2E) testing framework designed for decentralized applications (D<strong>Apps<\/strong>). Synpress supports both <strong>Playwright<\/strong> and <strong>Cypress<\/strong> as plugins and provides built-in features for handling <strong>MetaMask authentication, transactions, and wallet interactions.<\/strong><\/p>\n<p><strong>Install the Synpress framework command:<\/strong><\/p>\n<p>npm install &#8211;save-dev @synthetixio\/synpress @synthetixio\/synpress-tsconfig<\/p>\n<p><strong>Install Playwright framework command:<\/strong><\/p>\n<p>npm install &#8211;save-dev @playwright\/test<\/p>\n<h4><strong>Setup metamask\u00a0wallet:<\/strong><\/h4>\n<p>For manual UI testing, you can copy the private key from the Hardhat local network while running npx hardhat node and import the account into MetaMask like\u00a0this:<\/p>\n<p>During wallet setup with Synpress, it will create a new wallet for you. If you\u2019re using a Hardhat local network, you can simply use MetaMask\u2019s default seed phrase and any password for the wallet\u00a0setup.<\/p>\n<h4><strong>Here is how you can setup a MetaMask wallet with Synpress:<\/strong><\/h4>\n<p>The Synpress framework will look for a specific filename and folder for the wallet setup. You should name the file metamask.setup.ts, place it in the wallet-setup folder, and then run this\u00a0command:<\/p>\n<p>npx synpress wallet-setup<\/p>\n<p>In the video below, you will see that it opens a browser to create a MetaMask wallet and caches the wallet setup in the\u00a0.cache-synpress folder.<\/p>\n<p>After you have the wallet cache folder, you can simply run the Playwright command for your test\u00a0case.<\/p>\n<p>npx playwright test<\/p>\n<p>In the video below, you can see that Synpress helps manage the wallet plugin on the Chrome extension, simulating real user activities on the UI. You can create a script to automate confirming transactions on the MetaMask popup as\u00a0desired.<\/p>\n<p><strong>Playwright report\u00a0result:<\/strong><\/p>\n<h4><strong>Tips: Screenshot result report in Playwright<\/strong><\/h4>\n<p>You may already know that to capture test results in Playwright, you need to use await page.screenshot(). However, whether you want to record a <strong>screenshot<\/strong> or a <strong>video<\/strong>, Playwright records <strong>per\u00a0context<\/strong>.<\/p>\n<p>For example, during test execution, Playwright opens the <strong>Chrome extension (MetaMask) in the first tab<\/strong> and <strong>your DApp in the second tab<\/strong>. However, in our test reports, what we actually want to capture is the <strong>MetaMask popup<\/strong> showing the transaction details and gas\u00a0fees.<\/p>\n<h4><strong>How to Capture Both Main Page and Popup in Playwright?<\/strong><\/h4>\n<p>I created a <strong>custom function<\/strong> to capture screenshots of both the <strong>main page<\/strong> and the <strong>popup\u00a0page<\/strong>.<\/p>\n<p>Playwright can <strong>detect a popup session<\/strong> using context.waitForEvent(&#8216;page&#8217;)After capturing both images, I <strong>merge them into a single picture<\/strong> using the <strong>Sharp<\/strong>\u00a0library.<\/p>\n<p>You can see the implementation in the code\u00a0below.<\/p>\n<p><strong>Final Step:<\/strong><\/p>\n<p>Simply call the screenshot function and use testInfo.attach() to add it to the HTML\u00a0report.<\/p>\n<h4>Understand MetaMask functions in Synpress:<\/h4>\n<p>metamask.connectToDapp()<\/p>\n<p>When we use metamask.connectToDapp(), it <strong>automatically selects the default account<\/strong> in our MetaMask wallet and connects it to the DApp when we click the <strong>Connect<\/strong> button in the\u00a0UI.<\/p>\n<p>metamask.switchAccount(&#8216;Account 2&#8217;)<\/p>\n<p>This function switches the active account in MetaMask by specifying the account name. However, simply switching accounts in MetaMask does not automatically update the connected account in the DApp. The DApp must listen for MetaMask\u2019s account change events to detect and handle the switch properly.<\/p>\n<p>When clicking the \u201cConnect Wallet\u201d button, I check if an account is already connected. If it is, I first disconnect it and then reconnect.<\/p>\n<p>During automation, after switching accounts, MetaMask will automatically select <strong>Account 2<\/strong>, as shown\u00a0below.<\/p>\n<p>Similarly, when switching networks, the frontend must set up an event listener for MetaMask events, just like when switching accounts.<\/p>\n<p>this code is part of frontend\/utils\/web3.ts in\u00a0repometamask.switchNetwork(Local Optimism, true);metamask.confirmTransaction()<\/p>\n<p>This function is used when interacting with a DApp and performing a transaction that <strong>modifies the blockchain state<\/strong> (e.g., transferring tokens, updating balances, or writing data to storage). When this happens, <strong>MetaMask will require the user to confirm the transaction<\/strong> before it is executed.<\/p>\n<h4>Using Anvil for Network Simulation<\/h4>\n<p>Anvil is a local Ethereum development environment that\u2019s part of the Foundry suite of blockchain development tools. It\u2019s similar to Hardhat\u2019s network but with some key differences that make it particularly valuable for our testing scenario.<\/p>\n<p><strong>Anvil provides:<\/strong><\/p>\n<p>A customizable local Ethereum\u00a0nodePrecise control over chain ID, gas parameters, and block\u00a0timeThe ability to run multiple independent networks simultaneouslyAdvanced forking capabilities<\/p>\n<p><strong>Setting Up Multiple Networks:<\/strong><\/p>\n<p>\/\/ Start L1 Anvil node with realistic gas prices<br \/>const l1Node = spawn(&#8216;anvil&#8217;, [<br \/>  &#8216;&#8211;chain-id&#8217;, &#8216;31337&#8217;,<br \/>  &#8216;&#8211;base-fee&#8217;, gasPrices.l1.baseFee.toString(),<br \/>  &#8216;&#8211;host&#8217;, &#8216;0.0.0.0&#8217;,<br \/>  &#8216;&#8211;port&#8217;, &#8216;8545&#8217;,<br \/>  &#8216;&#8211;block-time&#8217;, &#8217;12&#8217;, \/\/ 12-second block times for Ethereum<br \/>  &#8216;&#8211;fork-url&#8217;, `https:\/\/eth-mainnet.g.alchemy.com\/v2\/${process.env.ALCHEMY_API_KEY}`,<br \/>  mainnetBlockNumber ? `&#8211;fork-block-number=${mainnetBlockNumber}` : &#8221;<br \/>]);<\/p>\n<p>\/\/ Start L2 Anvil node with lower gas prices<br \/>const l2Node = spawn(&#8216;anvil&#8217;, [<br \/>  &#8216;&#8211;chain-id&#8217;, &#8216;420&#8217;,<br \/>  &#8216;&#8211;base-fee&#8217;, forcedL2BaseFee.toString(),<br \/>  &#8216;&#8211;host&#8217;, &#8216;0.0.0.0&#8217;,<br \/>  &#8216;&#8211;port&#8217;, &#8216;8546&#8217;,<br \/>  &#8216;&#8211;block-time&#8217;, &#8216;2&#8217;, \/\/ 2-second block times for Optimism<br \/>  &#8216;&#8211;fork-url&#8217;, `https:\/\/opt-mainnet.g.alchemy.com\/v2\/${process.env.ALCHEMY_API_KEY}`,<br \/>  optimismBlockNumber ? `&#8211;fork-block-number=${optimismBlockNumber}` : &#8221;<br \/>]);<\/p>\n<p><strong>Real-time Gas\u00a0Updates:<\/strong><\/p>\n<p>This allows us to\u00a0have:<\/p>\n<p>Two separate networks running concurrently on localhostDifferent chain IDs for L1 (31337) and L2\u00a0(420)Different gas pricing to simulate L1\/L2 cost differencesIndependent state for each\u00a0network<\/p>\n<h4>Time Manipulation<\/h4>\n<p>Our tests rely heavily on time manipulation to test interest accrual and liquidations.<\/p>\n<p>Look at this function that checks interest value by advance time on blockchain:<\/p>\n<h4>Note on Local Testing Environment:<\/h4>\n<p>The lending smart contract calculates interest at 5% per year, which requires time progression to test properly. <strong><em>Unlike real networks, Hardhat\u2019s local blockchain doesn\u2019t automatically advance block timestamps<\/em><\/strong>. To simulate the passage of time for interest accumulation, we need to manually advance the blockchain.<\/p>\n<p>Similarly, <strong><em>health factor calculations depend on collateral price fluctuations<\/em><\/strong>. In a local environment, we need to implement a mock price oracle that can\u00a0either:<\/p>\n<p>Fetch real prices from external APIs like CoinMarketCap (useful for realistic scenarios)Allow manual price adjustments (essential for testing edge cases like liquidation events)<\/p>\n<p>These two simulation techniques enable comprehensive testing of all protocol states, including the critical liquidation process when a user\u2019s health factor falls below the threshold.<\/p>\n<h3>Testing Across Layer 1 and Layer 2\u00a0Networks<\/h3>\n<p>Our framework tests the same protocol deployed on different network\u00a0types:<\/p>\n<p><strong>Network Differences:<\/strong><\/p>\n<p><strong>L1 (Ethereum)<\/strong>: Higher gas costs, slower block\u00a0times<strong>L2 (Optimism)<\/strong>: Lower gas costs, faster block times, different transaction format<\/p>\n<h4>Cross-Network Test Scenarios<\/h4>\n<p>We\u2019ve implemented tests that\u00a0verify:<\/p>\n<p><strong>Network isolation<\/strong>: Positions on one network don\u2019t affect the\u00a0other<strong>Gas cost comparison<\/strong>: Compare transaction costs between L1 and\u00a0L2<strong>UI consistency<\/strong>: Verify the UI handles both networks correctly<\/p>\n<p>Here\u2019s a test step that verifies network isolation and gas\u00a0costs:<\/p>\n<p>During transactions on the DApp, we record the event type along with all relevant blockchain data, such as the chain ID, account, and gas cost, into the data column\u00a0below:<\/p>\n<p>Network Layer 2\u00a0Data:<\/p>\n<p>{<br \/>  &#8220;user&#8221;: &#8220;0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266&#8221;,<br \/>  &#8220;token&#8221;: &#8220;0x1343248Cbd4e291C6979e70a138f4c774e902561&#8221;,<br \/>  &#8220;amount&#8221;: &#8220;1&#8221;,<br \/>  &#8220;chainId&#8221;: 420,<br \/>  &#8220;gasMetrics&#8221;: {<br \/>    &#8220;baseFee&#8221;: &#8220;9826117&#8221;,<br \/>    &#8220;gasUsed&#8221;: &#8220;79381&#8221;,<br \/>    &#8220;gasPrice&#8221;: &#8220;1019652234&#8221;,<br \/>    &#8220;blockTime&#8221;: &#8220;2025-03-04T19:57:11.000Z&#8221;,<br \/>    &#8220;totalGasCost&#8221;: &#8220;80941013987154&#8221;<br \/>  }<br \/>}<\/p>\n<p>Network Layer 1\u00a0Data:<\/p>\n<p>{<br \/>  &#8220;user&#8221;: &#8220;0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266&#8221;,<br \/>  &#8220;token&#8221;: &#8220;0xF01f4567586c3A707EBEC87651320b2dd9F4A287&#8221;,<br \/>  &#8220;amount&#8221;: &#8220;1&#8221;,<br \/>  &#8220;chainId&#8221;: 31337,<br \/>  &#8220;gasMetrics&#8221;: {<br \/>    &#8220;baseFee&#8221;: &#8220;982611638&#8221;,<br \/>    &#8220;gasUsed&#8221;: &#8220;79381&#8221;,<br \/>    &#8220;gasPrice&#8221;: &#8220;2965223276&#8221;,<br \/>    &#8220;blockTime&#8221;: &#8220;2025-03-04T20:03:34.000Z&#8221;,<br \/>    &#8220;totalGasCost&#8221;: &#8220;235382388872156&#8221;<br \/>  }<br \/>}<\/p>\n<p>As seen in the data, Network Layer 2 has a lower gas cost compared to Network Layer 1. The total gas cost on Layer 2 is <strong><em>80,941,013,987,154<\/em><\/strong>, whereas on Layer 1, it is <strong><em>235,382,388,872,156<\/em><\/strong>.<\/p>\n<p>This means Layer 2 saves approximately <em>154,441,374,885,002<\/em> in gas costs, making it significantly more cost-efficient.<\/p>\n<h4>Why Test Across Networks?<\/h4>\n<p>While many users might interact with DeFi protocols on a single network, there are compelling reasons why testing across multiple networks is essential:<\/p>\n<h4>Real-World Cross-Network Usage:<\/h4>\n<p>Many DeFi applications today actually operate across multiple networks:<\/p>\n<p><strong>Bridge Protocols<\/strong>: Applications like Stargate, Hop Protocol, and Across connect assets between networks.<strong>Multi-Chain Deployments<\/strong>: Major DeFi protocols (Aave, Uniswap, etc.) deploy on multiple networks, and users often move between them based on gas\u00a0costs.<strong>L2 Migration Strategies<\/strong>: Users frequently deposit on L1 and then migrate to L2 for cheaper transactions as protocols expand.<strong>Cross-Chain Collateralization<\/strong>: Some advanced DeFi applications allow users to use collateral on one network to borrow on\u00a0another.<\/p>\n<p>Besides gas tracking in database testing from different network, as shown in the example above, we can also track transaction success rates and failures to analyze user behavior. This helps in <strong><em>conducting financial correctness tests and improving error handling<\/em><\/strong>.<\/p>\n<p>For example, if a user attempts to borrow <strong>0.8 ETH<\/strong> (which exceeds the <strong>75% collateral factor<\/strong>):<\/p>\n<p>Verify that an error is logged in the database.Check that the user\u2019s position remains unchanged.<\/p>\n<h4>Ready to Try It Yourself?<\/h4>\n<p>Now that you\u2019ve seen the flow, set up the project, and explored how to interact with MetaMask, it\u2019s time to get hands-on! This repo includes an <strong>E2E liquidation flow<\/strong> as an example, but feel free to <strong>extend it, experiment, and design your own test\u00a0cases<\/strong>.\ud83d\udd17 <strong>Check out the repo and start testing:<\/strong> [<a href=\"https:\/\/github.com\/Thanasornsawan\/end_to_end_testing_dapp_playwright_synpress\">Repo\u00a0Link<\/a>]Whether you\u2019re refining automation skills or exploring DeFi testing, this is your sandbox\u200a\u2014\u200ahave fun and break things (safely)! \ud83d\ude80<\/p>\n<p>Thanks for reading, and I hope you found this article helpful.<br \/>If you found this article helpful, give it a \ud83d\udc4f (or a few!) to help others discover\u00a0it!<\/p>\n<p><a href=\"https:\/\/medium.com\/coinmonks\/guideline-to-be-qa-web3-complete-e2e-defi-project-with-synpress-playwright-and-hardhat-anvil-5e3af494cca4\">Guideline to be QA Web3: Complete E2E DeFi Project with Synpress (Playwright) and Hardhat\/Anvil<\/a> was originally published in <a href=\"https:\/\/medium.com\/coinmonks\">Coinmonks<\/a> on Medium, where people are continuing the conversation by highlighting and responding to this story.<\/p>","protected":false},"excerpt":{"rendered":"<p>In my previous blog, QA Blockchain Testing: Smart Contract &amp; Network Performance with Hardhat, we explored the fundamentals of node testing for smart contracts. Today, we\u2019re taking the next step by diving into comprehensive testing for Web3 decentralized applications (DApps). Blockchain testing presents unique challenges for QA professionals. Many struggle with three key obstacles: limited [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-49763","post","type-post","status-publish","format-standard","hentry","category-interesting"],"_links":{"self":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/49763"}],"collection":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=49763"}],"version-history":[{"count":0,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/49763\/revisions"}],"wp:attachment":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=49763"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=49763"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=49763"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}