<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>weippig</title>
        <link>https://paragraph.com/@weippig</link>
        <description>undefined</description>
        <lastBuildDate>Tue, 28 Apr 2026 20:07:05 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[使用Hardhat與Infura部署合約 ]]></title>
            <link>https://paragraph.com/@weippig/hardhat-infura</link>
            <guid>VoKKtoA6aCHxjtBkpnrC</guid>
            <pubDate>Sun, 08 May 2022 04:42:32 GMT</pubDate>
            <description><![CDATA[原文發佈在個人網站小試身手1.Retrieve the Current Block Numbercurl [https://mainnet.infura.io/v3/](https://mainnet.infura.io/v3/YOUR-PROJECT-ID)YOUR_PROJECT_ID \ -X POST \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params": [],"id":1}' 回傳了以十六進制表示的block number：{"jsonrpc":"2.0","id":1,"result":"0xdf9bca"} 2.Check the Ether Balance For a Given Contractcurl [https://rinkeby.infura.io/v3/](https://mainnet.infura.io/v3/YOUR-PROJECT-ID)YOUR_PROJECT_ID \ -X POST \ -H "Co...]]></description>
            <content:encoded><![CDATA[<p>原文發佈在<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://weippig.com/2022/05/07/hardhat-infura.html">個人網站</a></p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">小試身手</h2><p>1.Retrieve the Current Block Number</p><pre data-type="codeBlock" text="curl [https://mainnet.infura.io/v3/](https://mainnet.infura.io/v3/YOUR-PROJECT-ID)YOUR_PROJECT_ID \
-X POST \
-H &quot;Content-Type: application/json&quot; \
-d &apos;{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;method&quot;:&quot;eth_blockNumber&quot;,&quot;params&quot;: [],&quot;id&quot;:1}&apos;
"><code>curl <span class="hljs-selector-attr">[https://mainnet.infura.io/v3/]</span>(https://mainnet.infura.io/v3/YOUR-PROJECT-ID)YOUR_PROJECT_ID \
-X POST \
-H "<span class="hljs-attribute">Content</span>-Type: application/json<span class="hljs-string">" \
-d '{"</span>jsonrpc<span class="hljs-string">":"</span><span class="hljs-number">2.0</span><span class="hljs-string">","</span>method<span class="hljs-string">":"</span>eth_blockNumber<span class="hljs-string">","</span>params<span class="hljs-string">": [],"</span>id<span class="hljs-string">":1}'
</span></code></pre><p>回傳了以十六進制表示的block number：<code>{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;id&quot;:1,&quot;result&quot;:&quot;0xdf9bca&quot;}</code></p><p>2.Check the Ether Balance For a Given Contract</p><pre data-type="codeBlock" text="curl [https://rinkeby.infura.io/v3/](https://mainnet.infura.io/v3/YOUR-PROJECT-ID)YOUR_PROJECT_ID \
-X POST \
-H &quot;Content-Type: application/json&quot; \
-d &apos;{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;method&quot;:&quot;eth_getBalance&quot;,&quot;params&quot;: [&quot;0xBf4eD7b27F1d666546E30D74d50d173d20bca754&quot;, &quot;latest&quot;],&quot;id&quot;:1}&apos;
"><code>curl <span class="hljs-selector-attr">[https://rinkeby.infura.io/v3/]</span>(https://mainnet.infura.io/v3/YOUR-PROJECT-ID)YOUR_PROJECT_ID \
-X POST \
-H "<span class="hljs-attribute">Content</span>-Type: application/json<span class="hljs-string">" \
-d '{"</span>jsonrpc<span class="hljs-string">":"</span><span class="hljs-number">2.0</span><span class="hljs-string">","</span>method<span class="hljs-string">":"</span>eth_getBalance<span class="hljs-string">","</span>params<span class="hljs-string">": ["</span><span class="hljs-number">0</span>xBf4eD7b27F1d666546E30D74d50d173d20bca754<span class="hljs-string">", "</span>latest<span class="hljs-string">"],"</span>id<span class="hljs-string">":1}'
</span></code></pre><p>回傳<code>{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;id&quot;:1,&quot;result&quot;:&quot;0x159fa21f4e8b7e715de0&quot;}</code> ，result中的字串代表合約的balance，單位是<em>wei</em>，一個<em>Ether</em>約等於10¹⁸ <em>wei</em>。</p><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">建立交易看看吧</h2><p>1.建立Ethereum帳號(可使用例如metamask) 2.建資料夾立然後進入</p><pre data-type="codeBlock" text="mkdir sendTransaction
cd sendTransaction
"><code><span class="hljs-built_in">mkdir</span> sendTransaction
<span class="hljs-built_in">cd</span> sendTransaction
</code></pre><p>3.安裝需要的packages</p><pre data-type="codeBlock" text="npm install web3
npm install dotenv --save
"><code>npm install web3
npm install dotenv <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save
</code></pre><p><em>💡 `dotenv` package用來讓使用者建立.env檔案、安全地存放本地環境變數。</em></p><p>4.建立<code>.env</code>檔案，內容：</p><pre data-type="codeBlock" text="ETHEREUM_NETWORK = &quot;rinkeby&quot;
INFURA_PROJECT_ID = &quot;&lt;Project-ID&gt;&quot;
SIGNER_PRIVATE_KEY = &quot;&lt;Private-Key&gt;&quot;
"><code><span class="hljs-attr">ETHEREUM_NETWORK</span> = <span class="hljs-string">"rinkeby"</span>
<span class="hljs-attr">INFURA_PROJECT_ID</span> = <span class="hljs-string">"&#x3C;Project-ID>"</span>
<span class="hljs-attr">SIGNER_PRIVATE_KEY</span> = <span class="hljs-string">"&#x3C;Private-Key>"</span>
</code></pre><ul><li><p><code>&lt;Project-ID&gt;</code> 在infura dashboard→setting 內可以找到</p></li><li><p><code>&lt;Private-Key&gt;</code> 以太坊帳號私鑰，導出metamask私鑰可看<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key">這篇</a></p></li><li><p>ETHEREUM_NETWORK 因自己在哪個網路而異，不一定是rinkeby</p></li></ul><p>5.建立<code>send.js</code>檔案，內容：</p><pre data-type="codeBlock" text="const Web3 = require(&quot;web3&quot;);

async function main() {
  // Configuring the connection to an Ethereum node
  const network = process.env.ETHEREUM_NETWORK;
  const web3 = new Web3(
    new Web3.providers.HttpProvider(
      `https://${network}.infura.io/v3/${process.env.INFURA_PROJECT_ID}`
    )
  );
  // Creating a signing account from a private key
  const signer = web3.eth.accounts.privateKeyToAccount(
    process.env.SIGNER_PRIVATE_KEY
  );
  web3.eth.accounts.wallet.add(signer);
  // Creating the transaction object
  const tx = {
    from: signer.address,
    to: &quot;0xAED01C776d98303eE080D25A21f0a42D94a86D9c&quot;,
    value: web3.utils.toWei(&quot;0.001&quot;),
  };
  // Assigning the right amount of gas
  tx.gas = await web3.eth.estimateGas(tx);

  // Sending the transaction to the network
  const receipt = await web3.eth
    .sendTransaction(tx)
    .once(&quot;transactionHash&quot;, (txhash) =&gt; {
      console.log(`Mining transaction ...`);
      console.log(`https://${network}.etherscan.io/tx/${txhash}`);
    });
  // The transaction is now on chain!
  console.log(`Mined in block ${receipt.blockNumber}`);
}

require(&quot;dotenv&quot;).config();
main();
"><code>const Web3 <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"web3"</span>);

async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Configuring the connection to an Ethereum node</span>
  const network <span class="hljs-operator">=</span> process.env.ETHEREUM_NETWORK;
  const web3 <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Web3(
    <span class="hljs-keyword">new</span> Web3.providers.HttpProvider(
      `https:<span class="hljs-comment">//${network}.infura.io/v3/${process.env.INFURA_PROJECT_ID}`</span>
    )
  );
  <span class="hljs-comment">// Creating a signing account from a private key</span>
  const signer <span class="hljs-operator">=</span> web3.eth.accounts.privateKeyToAccount(
    process.env.SIGNER_PRIVATE_KEY
  );
  web3.eth.accounts.wallet.add(signer);
  <span class="hljs-comment">// Creating the transaction object</span>
  const <span class="hljs-built_in">tx</span> <span class="hljs-operator">=</span> {
    <span class="hljs-keyword">from</span>: signer.<span class="hljs-built_in">address</span>,
    to: <span class="hljs-string">"0xAED01C776d98303eE080D25A21f0a42D94a86D9c"</span>,
    <span class="hljs-built_in">value</span>: web3.utils.toWei(<span class="hljs-string">"0.001"</span>),
  };
  <span class="hljs-comment">// Assigning the right amount of gas</span>
  <span class="hljs-built_in">tx</span>.gas <span class="hljs-operator">=</span> await web3.eth.estimateGas(<span class="hljs-built_in">tx</span>);

  <span class="hljs-comment">// Sending the transaction to the network</span>
  const receipt <span class="hljs-operator">=</span> await web3.eth
    .sendTransaction(<span class="hljs-built_in">tx</span>)
    .once(<span class="hljs-string">"transactionHash"</span>, (txhash) <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
      console.log(`Mining transaction ...`);
      console.log(`https:<span class="hljs-comment">//${network}.etherscan.io/tx/${txhash}`);</span>
    });
  <span class="hljs-comment">// The transaction is now on chain!</span>
  console.log(`Mined in <span class="hljs-built_in">block</span> ${receipt.blockNumber}`);
}

<span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config();
main();
</code></pre><p>6.執行</p><p>7.可到輸出結果第二行的網址查看細節</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8f3ab889bc03dcecfa5eada3a3e3973ce0104335229fc87a4cde0dde74a8517e.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><hr><h2 id="h-hardhat" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">結合Hardhat部署合約到測試鏈上吧</h2><hr><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">前置作業</h3><p>1.安裝Hardhat</p><pre data-type="codeBlock" text="npm install --save-dev hardhat
"><code>npm install <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev hardhat
</code></pre><p>2.建立資料夾並進入</p><pre data-type="codeBlock" text="mkdir infura_project
cd infura_project
"><code><span class="hljs-built_in">mkdir</span> infura_project
<span class="hljs-built_in">cd</span> infura_project
</code></pre><p>3.建立Hardhat project，選擇第一個 <em>Create a basic sample project</em></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ce93d988de238c2237dc8daba1979da4cdd91312fb36e8f649dffd55afa6cde3.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>4.MacOS的環境下，可以使用 <code>tree -L 1</code> 指令印出第一層資料夾樹狀結構，沒有安裝過<code>tree</code>的話，可透過 <code>brew install tree</code> 安裝</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c706864565a2945c678d50ea25031bc3b486b811c8bf0b768b4424aeddc41130.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><hr><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">撰寫合約與測試</h3><p>1.將contract資料夾底下的<code>Greeter.sol</code>改名為<code>Demo.sol</code>，替換程式碼內容為：</p><pre data-type="codeBlock" text="//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;

contract Demo is Ownable{
    uint256 private _value = 0;
    event ValueChanged(uint256 value);

    function store(uint256 value) public onlyOwner {
        _value = value;
        emit ValueChanged(value);
    }

    function retrieve() public view returns (uint256) {
        return _value;
    }
}
"><code><span class="hljs-comment">//SPDX-License-Identifier: Unlicense</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/access/Ownable.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Demo</span> <span class="hljs-keyword">is</span> <span class="hljs-title">Ownable</span></span>{
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">private</span> _value <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">ValueChanged</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> value</span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">store</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> value</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
        _value <span class="hljs-operator">=</span> value;
        <span class="hljs-keyword">emit</span> ValueChanged(value);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">retrieve</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">return</span> _value;
    }
}
</code></pre><p>2.合約需要用到openzepplin的Ownable.sol，使用指令安裝@openzeppelin/contracts</p><pre data-type="codeBlock" text="npm install @openzeppelin/contracts
"><code>npm install @openzeppelin/contracts
</code></pre><p>3.編譯合約看看</p><p>會列印出 <em>Compiled 3 Solidity files successfully</em>，資料夾目錄底下多出<code>artifacts</code>和<code>cache</code>兩個資料夾</p><p>4.將test資料夾底下的<code>sample-test.js</code> 改名為<code>Demo.test.ts</code>，內容為：</p><pre data-type="codeBlock" text="import { expect } from &apos;chai&apos;
import { ethers } from &apos;hardhat&apos;

// Start test block
describe(&apos;Demo&apos;, function () {
  before(async function () {
    this.Demo = await ethers.getContractFactory(&apos;Demo&apos;)
  })

  beforeEach(async function () {
    this.demo = await this.Demo.deploy()
    await this.demo.deployed()
  })

  // Test case
  it(&apos;retrieve returns a value previously stored&apos;, async function () {
    // Store a value
    await this.demo.store(42)

    // Test if the returned value is the same one
    // Note that we need to use strings to compare the 256 bit integers
    expect((await this.demo.retrieve()).toString()).to.equal(&apos;42&apos;)
  })
})
"><code><span class="hljs-keyword">import</span> { expect } <span class="hljs-keyword">from</span> <span class="hljs-string">'chai'</span>
<span class="hljs-keyword">import</span> { ethers } <span class="hljs-keyword">from</span> <span class="hljs-string">'hardhat'</span>

<span class="hljs-comment">// Start test block</span>
<span class="hljs-title function_">describe</span>(<span class="hljs-string">'Demo'</span>, <span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) {
  <span class="hljs-title function_">before</span>(<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) {
    <span class="hljs-variable language_">this</span>.<span class="hljs-property">Demo</span> = <span class="hljs-keyword">await</span> ethers.<span class="hljs-title function_">getContractFactory</span>(<span class="hljs-string">'Demo'</span>)
  })

  <span class="hljs-title function_">beforeEach</span>(<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) {
    <span class="hljs-variable language_">this</span>.<span class="hljs-property">demo</span> = <span class="hljs-keyword">await</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">Demo</span>.<span class="hljs-title function_">deploy</span>()
    <span class="hljs-keyword">await</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">demo</span>.<span class="hljs-title function_">deployed</span>()
  })

  <span class="hljs-comment">// Test case</span>
  <span class="hljs-title function_">it</span>(<span class="hljs-string">'retrieve returns a value previously stored'</span>, <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) {
    <span class="hljs-comment">// Store a value</span>
    <span class="hljs-keyword">await</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">demo</span>.<span class="hljs-title function_">store</span>(<span class="hljs-number">42</span>)

    <span class="hljs-comment">// Test if the returned value is the same one</span>
    <span class="hljs-comment">// Note that we need to use strings to compare the 256 bit integers</span>
    <span class="hljs-title function_">expect</span>((<span class="hljs-keyword">await</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">demo</span>.<span class="hljs-title function_">retrieve</span>()).<span class="hljs-title function_">toString</span>()).<span class="hljs-property">to</span>.<span class="hljs-title function_">equal</span>(<span class="hljs-string">'42'</span>)
  })
})
</code></pre><p>這時候會報錯，這是因為我們接下來會用typescript進行開發，需要更改package.json內容：</p><pre data-type="codeBlock" text="{
  &quot;name&quot;: &quot;hardhat-project&quot;,
  &quot;devDependencies&quot;: {
    &quot;@nomiclabs/hardhat-ethers&quot;: &quot;^2.0.5&quot;,
    &quot;@nomiclabs/hardhat-waffle&quot;: &quot;^2.0.3&quot;,
    &quot;@types/chai&quot;: &quot;^4.3.1&quot;,
    &quot;@types/mocha&quot;: &quot;^9.1.1&quot;,
    &quot;@types/node&quot;: &quot;^17.0.27&quot;,
    &quot;chai&quot;: &quot;^4.3.6&quot;,
    &quot;dotenv&quot;: &quot;^16.0.0&quot;,
    &quot;ethereum-waffle&quot;: &quot;^3.4.4&quot;,
    &quot;ethers&quot;: &quot;^5.6.4&quot;,
    &quot;hardhat&quot;: &quot;^2.9.3&quot;,
    &quot;mocha&quot;: &quot;^9.2.2&quot;,
    &quot;solc&quot;: &quot;^0.8.13&quot;,
    &quot;ts-node&quot;: &quot;^10.7.0&quot;,
    &quot;typescript&quot;: &quot;^4.6.3&quot;,
    &quot;web3&quot;: &quot;^1.7.3&quot;
  },
  &quot;dependencies&quot;: {
    &quot;@openzeppelin/contracts&quot;: &quot;^4.5.0&quot;,
    &quot;@typechain/hardhat&quot;: &quot;^6.0.0&quot;
  }
}
"><code>{
  <span class="hljs-string">"name"</span>: <span class="hljs-string">"hardhat-project"</span>,
  <span class="hljs-string">"devDependencies"</span>: {
    <span class="hljs-string">"@nomiclabs/hardhat-ethers"</span>: <span class="hljs-string">"^2.0.5"</span>,
    <span class="hljs-string">"@nomiclabs/hardhat-waffle"</span>: <span class="hljs-string">"^2.0.3"</span>,
    <span class="hljs-string">"@types/chai"</span>: <span class="hljs-string">"^4.3.1"</span>,
    <span class="hljs-string">"@types/mocha"</span>: <span class="hljs-string">"^9.1.1"</span>,
    <span class="hljs-string">"@types/node"</span>: <span class="hljs-string">"^17.0.27"</span>,
    <span class="hljs-string">"chai"</span>: <span class="hljs-string">"^4.3.6"</span>,
    <span class="hljs-string">"dotenv"</span>: <span class="hljs-string">"^16.0.0"</span>,
    <span class="hljs-string">"ethereum-waffle"</span>: <span class="hljs-string">"^3.4.4"</span>,
    <span class="hljs-string">"ethers"</span>: <span class="hljs-string">"^5.6.4"</span>,
    <span class="hljs-string">"hardhat"</span>: <span class="hljs-string">"^2.9.3"</span>,
    <span class="hljs-string">"mocha"</span>: <span class="hljs-string">"^9.2.2"</span>,
    <span class="hljs-string">"solc"</span>: <span class="hljs-string">"^0.8.13"</span>,
    <span class="hljs-string">"ts-node"</span>: <span class="hljs-string">"^10.7.0"</span>,
    <span class="hljs-string">"typescript"</span>: <span class="hljs-string">"^4.6.3"</span>,
    <span class="hljs-string">"web3"</span>: <span class="hljs-string">"^1.7.3"</span>
  },
  <span class="hljs-string">"dependencies"</span>: {
    <span class="hljs-string">"@openzeppelin/contracts"</span>: <span class="hljs-string">"^4.5.0"</span>,
    <span class="hljs-string">"@typechain/hardhat"</span>: <span class="hljs-string">"^6.0.0"</span>
  }
}
</code></pre><p>再執行一次 <code>npm install</code> ，回到<code>Demo.test.ts</code>就看不到紅字了！</p><p>5.更改<code>hardhat.config.js</code>成<code>.ts</code>，檔頭<code>require(&quot;@nomiclabs/hardhat-waffle&quot;);</code> 改為</p><pre data-type="codeBlock" text="import { task } from &quot;hardhat/config&quot;;
import &quot;@nomiclabs/hardhat-waffle&quot;;
import &quot;@nomiclabs/hardhat-ethers&quot;;
"><code><span class="hljs-keyword">import</span> { task } <span class="hljs-keyword">from</span> <span class="hljs-string">"hardhat/config"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@nomiclabs/hardhat-waffle"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@nomiclabs/hardhat-ethers"</span>;
</code></pre><p>6.添加<code>tsconfig.json</code>檔案</p><pre data-type="codeBlock" text="{
  &quot;compilerOptions&quot;: {
    &quot;target&quot;: &quot;ES2017&quot;,
    &quot;module&quot;: &quot;commonjs&quot;,
    &quot;declaration&quot;: true,
    &quot;declarationMap&quot;: true,
    &quot;sourceMap&quot;: true,
    &quot;outDir&quot;: &quot;./dist&quot;,
    &quot;strict&quot;: true,
    &quot;rootDirs&quot;: [&quot;./src&quot;, &quot;./scripts&quot;, &quot;./test&quot;],
    &quot;esModuleInterop&quot;: true
  },
  &quot;exclude&quot;: [&quot;dist&quot;, &quot;node_modules&quot;],
  &quot;include&quot;: [&quot;./test&quot;, &quot;./src&quot;, &quot;./scripts&quot;],
  &quot;files&quot;: [&quot;./hardhat.config.ts&quot;]
}
"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"compilerOptions"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"target"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ES2017"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"module"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"commonjs"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"declaration"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"declarationMap"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"sourceMap"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"outDir"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"./dist"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"strict"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"rootDirs"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"./src"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"./scripts"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"./test"</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"esModuleInterop"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"exclude"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"dist"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"node_modules"</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"include"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"./test"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"./src"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"./scripts"</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"files"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"./hardhat.config.ts"</span><span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre><p>7.使用 <code>npx hardhat test</code> 指令進行測試，順利的話，最後會出現 1 passing</p><hr><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">撰寫腳本進行部署</h3><p>1.將scripts資料夾下的<code>sample-scripts.js</code>更改為<code>deploy.ts</code>，內容為：</p><pre data-type="codeBlock" text="import { ethers } from &quot;hardhat&quot;;

async function main() {
  const [deployer] = await ethers.getSigners(); //get the account to deploy the contract

  console.log(&quot;Deploying contracts with the account:&quot;, deployer.address); 

  const Demo = await ethers.getContractFactory(&quot;Demo&quot;); // Getting the Contract
  const demo = await Demo.deploy(); //deploying the contract

  await demo.deployed(); // waiting for the contract to be deployed

  console.log(&quot;Demo deployed to:&quot;, demo.address); // Returning the contract address on the rinkeby
}

main()
  .then(() =&gt; process.exit(0))
  .catch((error) =&gt; {
    console.error(error);
    process.exit(1);
  }); // Calling the function to deploy the contract
"><code><span class="hljs-keyword">import</span> { <span class="hljs-title">ethers</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"hardhat"</span>;

async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  const [deployer] <span class="hljs-operator">=</span> await ethers.getSigners(); <span class="hljs-comment">//get the account to deploy the contract</span>

  console.log(<span class="hljs-string">"Deploying contracts with the account:"</span>, deployer.<span class="hljs-built_in">address</span>); 

  const Demo <span class="hljs-operator">=</span> await ethers.getContractFactory(<span class="hljs-string">"Demo"</span>); <span class="hljs-comment">// Getting the Contract</span>
  const demo <span class="hljs-operator">=</span> await Demo.deploy(); <span class="hljs-comment">//deploying the contract</span>

  await demo.deployed(); <span class="hljs-comment">// waiting for the contract to be deployed</span>

  console.log(<span class="hljs-string">"Demo deployed to:"</span>, demo.<span class="hljs-built_in">address</span>); <span class="hljs-comment">// Returning the contract address on the rinkeby</span>
}

main()
  .then(() <span class="hljs-operator">=</span><span class="hljs-operator">></span> process.exit(<span class="hljs-number">0</span>))
  .catch((<span class="hljs-function"><span class="hljs-keyword">error</span>) => </span>{
    console.error(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
    process.exit(<span class="hljs-number">1</span>);
  }); <span class="hljs-comment">// Calling the function to deploy the contract</span>
</code></pre><p>2.在<code>hardhat.config.ts</code>中配置網路，添加在<code>solidity: &quot;0.8.4&quot;</code>後面</p><pre data-type="codeBlock" text="export default {
  solidity: &quot;0.8.4&quot;,
  defaultNetwork: &quot;rinkeby&quot;,
  networks: {
    hardhat: {
    },
    rinkeby: {
      url: &quot;https://rinkeby.infura.io/v3/YOUR_PROJECT_ID&quot;, //Infura url with projectId
      accounts: [&quot;YOUR_ACCOUNT_PRIVATE_KEY&quot;] // add the account that will deploy the contract (pay gas fee)
    }
  },
"><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  solidity: <span class="hljs-string">"0.8.4"</span>,
  defaultNetwork: <span class="hljs-string">"rinkeby"</span>,
  networks: {
    hardhat: {
    },
    rinkeby: {
      url: <span class="hljs-string">"https://rinkeby.infura.io/v3/YOUR_PROJECT_ID"</span>, <span class="hljs-comment">//Infura url with projectId</span>
      accounts: [<span class="hljs-string">"YOUR_ACCOUNT_PRIVATE_KEY"</span>] <span class="hljs-comment">// add the account that will deploy the contract (pay gas fee)</span>
    }
  },
</code></pre><p>3.執行指令 <code>TS_NODE_FILES=true ts-node scripts/deploy.ts</code> ，如果是使用測試鏈，可能需要等待比較久的時間，成功後應該會看到結果：</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e1c2302f9db0b9fa72b96c995f4e523eb021e58ae9a51e7f194bbfe9711a5f55.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>上面是部署合約、支付gas fee的帳號，下面是合約地址，把合約地址複製起來，去Etherscan看看：</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/29e1bc72f8996a64ff9d2478692d61a233117cc3856870ba7910f2b25ba0a258.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>4.在scrips資料夾底下建立叫做<code>storeAndRetrieve.ts</code>的新檔案，測試剛剛部署好的合約的兩個function，<code>store()</code>和<code>retrieve()</code></p><pre data-type="codeBlock" text="import { ethers } from &quot;hardhat&quot;;

async function main () {
    const accounts = await ethers.provider.listAccounts();

    const address = &apos;YOUR_CONTRACT_ADDRESS&apos;;
    const Demo = await ethers.getContractFactory(&apos;Demo&apos;);
    const demo = await Demo.attach(address);

    // Call the retrieve() function of the deployed Box contract
    let value = await demo.retrieve();
    console.log(&apos;demo value is&apos;, value.toString());
}
  
main()
  .then(() =&gt; process.exit(0))
  .catch(error =&gt; {
  console.error(error);
  process.exit(1);
  });
"><code><span class="hljs-keyword">import</span> { <span class="hljs-title">ethers</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"hardhat"</span>;

async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span> (<span class="hljs-params"></span>) </span>{
    const accounts <span class="hljs-operator">=</span> await ethers.provider.listAccounts();

    const <span class="hljs-keyword">address</span> <span class="hljs-operator">=</span> <span class="hljs-string">'YOUR_CONTRACT_ADDRESS'</span>;
    const Demo <span class="hljs-operator">=</span> await ethers.getContractFactory(<span class="hljs-string">'Demo'</span>);
    const demo <span class="hljs-operator">=</span> await Demo.attach(<span class="hljs-keyword">address</span>);

    <span class="hljs-comment">// Call the retrieve() function of the deployed Box contract</span>
    let value <span class="hljs-operator">=</span> await demo.retrieve();
    console.log(<span class="hljs-string">'demo value is'</span>, value.toString());
}
  
main()
  .then(() <span class="hljs-operator">=</span><span class="hljs-operator">></span> process.exit(<span class="hljs-number">0</span>))
  .catch(<span class="hljs-function"><span class="hljs-keyword">error</span> => </span>{
  console.error(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
  process.exit(<span class="hljs-number">1</span>);
  });
</code></pre><p>5.使用 <code>TS_NODE_FILES=true ts-node scripts/storeAndRetrieve.ts</code> 指令執行，會呼叫合約中的<code>retrieve()</code>，印出_value原始的值0。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">監聽合約事件</h3><p>1.在主目錄底下建立src資料夾，裡面建立一個做<code>eventListener.ts</code>的檔案</p><pre data-type="codeBlock" text="import { ethers } from &apos;hardhat&apos;

async function listenEvent () {
  const address = &apos;YOUR_CONTRACT_ADDRESS&apos;
  const Demo = await ethers.getContractFactory(&apos;Demo&apos;)
  const demo = await Demo.attach(address)

  demo.on(&apos;ValueChanged&apos;, async (event: any) =&gt; {
    console.log(event)
  })
}

listenEvent()
"><code>import { ethers } <span class="hljs-keyword">from</span> <span class="hljs-string">'hardhat'</span>

<span class="hljs-function"><span class="hljs-keyword">async</span> function <span class="hljs-title">listenEvent</span> ()</span> {
  <span class="hljs-keyword">const</span> address = <span class="hljs-string">'YOUR_CONTRACT_ADDRESS'</span>
  <span class="hljs-keyword">const</span> Demo = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">'Demo'</span>)
  <span class="hljs-keyword">const</span> demo = <span class="hljs-keyword">await</span> Demo.attach(address)

  demo.<span class="hljs-keyword">on</span>(<span class="hljs-string">'ValueChanged'</span>, <span class="hljs-keyword">async</span> (<span class="hljs-keyword">event</span>: any) => {
    console.log(<span class="hljs-keyword">event</span>)
  })
}

listenEvent()
</code></pre><p>2.修改storeAndRetrieve.ts，在<code>let value = await demo.retrieve();</code> 前面加上三行，代表呼叫合約中的<code>store(uint value)</code>，並變更<code>_value</code>的值成100</p><pre data-type="codeBlock" text="// Send a transaction to store() a new value
    let storeValue = await demo.store(100);
    await storeValue.wait();
"><code><span class="hljs-comment">// Send a transaction to store() a new value</span>
    let storeValue <span class="hljs-operator">=</span> await demo.store(<span class="hljs-number">100</span>);
    await storeValue.wait();
</code></pre><p>3.執行指令 <code>TS_NODE_FILES=true ts-node src/eventListener.ts</code> 持續監聽合約內的事件 <code>ValueChanged</code></p><p>4.在新的terminal分頁執行 <code>TS_NODE_FILES=true ts-node scripts/storeAndRetrieve.ts</code></p><p>5.過了一陣子，回到剛剛執行<code>eventListener.ts</code>的地方，因為呼叫store function來存入100，觸發了事件<code>ValueChanged</code>，合約監聽器會印出BigNumber { value: “100” }</p><p>6.可以回到Etherscan做確認，應該會看到兩筆交易，兩筆事件</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/41e53e29bc9144b13f03e951e2fa08f8c68e976fcd72502848683c07b31a4cfb.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6932045e2c3b158f52182f1f7c1655d2f3a0229d36c1c7159b1b9461c6c7f9ce.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>資料來源：</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.infura.io/getting-started-with-infura-28e41844cc89/">Getting Started With Infura</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.openzeppelin.com/learn/deploying-and-interacting#calling-the-contract">Deploying and interacting with smart contracts</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hardhat.org/guides/typescript.html">Hardhat-typescript</a></p></li></ul>]]></content:encoded>
            <author>weippig@newsletter.paragraph.com (weippig)</author>
        </item>
    </channel>
</rss>