<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Rustam Khasanshin</title>
    <link>https://khasanshin.com/</link>
    <description>Recent content on Rustam Khasanshin</description>
    <generator>Hugo</generator>
    <language>en</language>
    <copyright>© 2026 Rustam Khasanshin</copyright>
    <lastBuildDate>Mon, 19 Sep 2022 19:46:31 +0200</lastBuildDate>
    <atom:link href="https://khasanshin.com/rss.xml" rel="self" type="application/rss+xml" />
    
    
    
    
    <item>
      <title>Smart contract method call in Go</title>
      <link>https://khasanshin.com/posts/smart-contract-method-call-in-go/</link>
      <pubDate>Mon, 19 Sep 2022 19:46:31 +0200</pubDate>
      <guid>https://khasanshin.com/posts/smart-contract-method-call-in-go/</guid>
      <description>&lt;p&gt;Consider a blockchain method in Go. Suppose you have a contract in the etherium blockchain and you want to call its method.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Consider a blockchain method in Go. Suppose you have a contract in the etherium blockchain and you want to call its method.</p>
<p>The main library for dealing with such contracts is <a href="https://pkg.go.dev/github.com/ethereum/go-ethereum/ethclient">https://pkg.go.dev/github.com/ethereum/go-ethereum/ethclient</a>. Let&rsquo;s take for example <a href="https://bscscan.com/token/0xE0b1EF69BC4AB4173989C1190f0d77A813f3B726">my friends&rsquo; token</a> contract running on the binance blockchain (also based on ether) and try calling the method to get the total number of tokens.</p>
<p>First, we need to create a client instance to connect to our blockchain and then make requests to it.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span>
</span></span><span class="line"><span class="cl">    <span class="s">&#34;github.com/ethereum/go-ethereum/ethclient&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">client</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ethclient</span><span class="p">.</span><span class="nf">Dial</span><span class="p">(</span><span class="s">&#34;https://bsc-dataseed.binance.org/&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Now we have to decide how we will interact with the contract.</p>
<blockquote>
<p>In javascript, calling the contract method is easy enough - you can load the contract ABI and the web3 library will do everything. In Go, it&rsquo;s a bit tricky.</p></blockquote>
<p>In order to call a method in Go, you have to write that method. It makes sense. And the same logic works with contracts. But to rewrite all the methods is long and tedious, so people invented code generation for this contract from its ABI. For this, we need the <code>abigen</code> library. You can get it on your mac via Homebrew.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ brew tap ethereum/ethereum
</span></span><span class="line"><span class="cl">$ brew install ethereum
</span></span></code></pre></div><p>To check if the installation was successful, try to output the abigen version.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ abigen -v
</span></span><span class="line"><span class="cl">&gt; abigen version 1.10.25-stable
</span></span></code></pre></div><p>Abigen successfully installed, time to generate Go code. Go to the contract page in bscscan — <a href="https://bscscan.com/address/0xE0b1EF69BC4AB4173989C1190f0d77A813f3B726">https://bscscan.com/address/0xE0b1EF69BC4AB4173989C1190f0d77A813f3B726</a>, and download its ABI.</p>
<p>Contract -&gt; Code -&gt; Contract ABI -&gt; Export ABI -&gt; RAW/Text Format.</p>
<p>Save the file in the programm directory and name it token.abi. Next we call abigen. The <code>--abi</code> parameter specifies our ABI file, the <code>--pkg</code> parameter specifies the name of the package for our Go code, the <code>--type</code> parameter specifies the name of the structure to which all methods will be bound, the <code>--out</code> parameter specifies the name of the Go file.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ abigen --abi<span class="o">=</span>token.abi --pkg<span class="o">=</span>main --type<span class="o">=</span>token --out<span class="o">=</span>token.go
</span></span></code></pre></div><p>The file token.go with the code should appear in the directory. It can already be used. But first let&rsquo;s create an address instance from our string contract address. We need it to create an instance of the token afterwards. This is done using the library github.com/ethereum/go-ethereum/common.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span>
</span></span><span class="line"><span class="cl">    <span class="s">&#34;github.com/ethereum/go-ethereum/common&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">address</span> <span class="o">:=</span> <span class="nx">common</span><span class="p">.</span><span class="nf">HexToAddress</span><span class="p">(</span><span class="s">&#34;0xE0b1EF69BC4AB4173989C1190f0d77A813f3B726&#34;</span><span class="p">)</span>
</span></span></code></pre></div><p>Now create the actual token instance itself.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">token</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nf">NewToken</span><span class="p">(</span><span class="nx">address</span><span class="p">,</span> <span class="nx">client</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>And try to call a method to get the total number of tokens - <code>TotalSupply</code>. But this method requires passing parameters of special type <code>&amp;bind.CallOpts{}</code>. We don&rsquo;t want to pass parameters, but we need to pass an empty value. And the type itself can be loaded from library github.com/ethereum/go-ethereum/accounts/abi/bind.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;github.com/ethereum/go-ethereum/accounts/abi/bind&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">totalSupply</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">token</span><span class="p">.</span><span class="nf">TotalSupply</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">bind</span><span class="p">.</span><span class="nx">CallOpts</span><span class="p">{})</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>In general at this stage we can already observe the total number of tokens in <code>totalSupply</code>. But we cannot know whether this token is divisible or not. And it may be that the resulting value may be fractional, but we don&rsquo;t know where the point is.  To understand how much this token is divisible, we need to know its <code>Decimals</code> parameter. For this, we have a special method.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">decimals</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">token</span><span class="p">.</span><span class="nf">Decimals</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">bind</span><span class="p">.</span><span class="nx">CallOpts</span><span class="p">{})</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Simply put, the Decimals parameter is the number of digits after the dot. Creating a floating point number and displaying it correctly is worthy of a separate article. So let&rsquo;s just display the floating point number using what we have.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">s</span> <span class="o">:=</span> <span class="nx">totalSupply</span><span class="p">.</span><span class="nf">String</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">s</span><span class="p">[:</span><span class="nb">len</span><span class="p">(</span><span class="nx">s</span><span class="p">)</span><span class="o">-</span><span class="nb">int</span><span class="p">(</span><span class="nx">decimals</span><span class="p">)]</span> <span class="o">+</span> <span class="s">&#34;.&#34;</span> <span class="o">+</span> <span class="nx">s</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="nx">s</span><span class="p">)</span><span class="o">-</span><span class="nb">int</span><span class="p">(</span><span class="nx">decimals</span><span class="p">):])</span>
</span></span></code></pre></div><p>That&rsquo;s pretty much it. We have learned how to connect to the blockchain and call a contract method with a return value. The source code can be found on the <a href="https://github.com/Rustery/rustery-go-eth-client">github</a>.</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
