[Go] Web3 Use Smart Contract Query Wallet Multi Balance

陳兆煇 Harvey
1 min readMay 9, 2023

--

使用 github.com/ethereum/go-ethereum , 查詢鏈上錢包多幣種餘額

  1. 智能合約是 MutiCall
    Multicall | Address 0xeefba1e63905ef1d7acba5a8513c70307c1ce441 | Etherscan
  2. 這邊也會使用到 ERC20 的 ABI
    Google 一下複製下來就行
func main() {
client, err := ethclient.Dial("https://mainnet.infura.io/v3/21e4ec6a577c4062a7a097278a55d9eb")
if err != nil {
log.Fatalf("Failed to connect to the Ethereum client: %v", err)
}

erc20Abi, err := abi.JSON(strings.NewReader(ERC20ABI))
if err != nil {
panic(err)
}

b, _ := os.ReadFile("./multi_call.abi")
multiABI, err := abi.JSON(bytes.NewReader(b))
if err != nil {
panic(err)
}

// 查詢 0x00192Fb10dF37c9FB26829eb2CC623cd1BF599E8 的餘額
balanceOf, _ := erc20Abi.Pack("balanceOf", common.HexToAddress("0x00192Fb10dF37c9FB26829eb2CC623cd1BF599E8"))
// 使用 智能合約裡面的 aggregate 方法
b, err = multiABI.Pack("aggregate", []Struct0{
{
// 什麼樣的幣種
Target: common.HexToAddress("0x86b78c93Eea132BFD942E1f316bAB02A127dfC84"),
CallData: balanceOf,
},
{
// 什麼樣的幣種
Target: common.HexToAddress("0x1dd34B35d96f5159567EF4caD2c69C0f87c3195c"),
CallData: balanceOf,
},
})
if err != nil {
panic(err)
}

multiCallContract := common.HexToAddress("0xeefba1e63905ef1d7acba5a8513c70307c1ce441")
b, err = client.CallContract(context.Background(), ethereum.CallMsg{
To: &multiCallContract,
Data: b,
}, nil)
if err != nil {
fmt.Printf("%+v %+v\n", b, err)
return
}

var out AggregateResponse

err = multiABI.UnpackIntoInterface(&out, "aggregate", b)
if err != nil {
fmt.Printf("%+v %+v\n", b, err)
}

for _, i := range out.ReturnData {
out, _ := erc20Abi.Unpack("balanceOf", i[:])
fmt.Printf("%+v\n", out)
}
}

這邊主要用到 “github.com/ethereum/go-ethereum/accounts/abi”
會用到 Pack, Unpack, 大概就是 json marshal, unMarshal 的意思

跟智能合約的交互 http 沒什麼差別, 都是 Request Response, 主要是 Build Request Response 會有點麻煩

--

--