Support single request

Outputs type supports nil
This commit is contained in:
ziyeziye 2023-12-11 15:47:34 +08:00
parent 9467c4ddaa
commit 1fbee12081
3 changed files with 81 additions and 6 deletions

View file

@ -19,6 +19,7 @@ go get github.com/forta-network/go-multicall
(See other examples under the `examples` directory!)
#### Multicall
```go
package main
@ -91,3 +92,64 @@ func main() {
}
}
```
#### SingleCall
```go
package main
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/forta-network/go-multicall"
)
const (
APIURL = "https://cloudflare-eth.com"
ERC20ABI = `[
{
"constant":true,
"inputs":[
{
"name":"tokenOwner",
"type":"address"
}
],
"name":"balanceOf",
"outputs":[
{
"name":"balance",
"type":"uint256"
}
],
"payable":false,
"stateMutability":"view",
"type":"function"
}
]`
)
func main() {
caller, err := multicall.Dial(context.Background(), APIURL)
if err != nil {
panic(err)
}
contract, err := multicall.NewContract(ERC20ABI, "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")
if err != nil {
panic(err)
}
single, err := caller.CallSingle(nil,
contract.NewCall(
nil,
"balanceOf",
common.HexToAddress("0xcEe284F754E854890e311e3280b767F80797180d"), // Arbitrum One gateway
).Name("Arbitrum One gateway balance"))
if err != nil {
return
}
fmt.Println(single.CallName, ":", single.Outputs, err)
}
```

10
call.go
View file

@ -2,7 +2,6 @@ package multicall
import (
"bytes"
"errors"
"fmt"
"reflect"
@ -80,15 +79,16 @@ func (call *Call) Unpack(b []byte) error {
if t.Kind() == reflect.Pointer {
t = t.Elem()
}
if t.Kind() != reflect.Struct {
return errors.New("outputs type is not a struct")
}
out, err := call.Contract.ABI.Unpack(call.Method, b)
if err != nil {
return fmt.Errorf("failed to unpack '%s' outputs: %v", call.Method, err)
}
if t.Kind() != reflect.Struct {
call.Outputs = out
return nil
}
fieldCount := t.NumField()
for i := 0; i < fieldCount; i++ {
field := t.Field(i)

View file

@ -47,6 +47,19 @@ func Dial(ctx context.Context, rawUrl string, multicallAddr ...string) (*Caller,
// Call makes multicalls.
func (caller *Caller) Call(opts *bind.CallOpts, calls ...*Call) ([]*Call, error) {
return caller.calls(opts, calls...)
}
func (caller *Caller) CallSingle(opts *bind.CallOpts, call *Call) (*Call, error) {
calls, err := caller.calls(opts, call)
if err != nil {
return call, fmt.Errorf("CallSingle failed: %v", err)
}
return calls[0], nil
}
func (caller *Caller) calls(opts *bind.CallOpts, calls ...*Call) ([]*Call, error) {
var multiCalls []contract_multicall.Multicall3Call3
for i, call := range calls {
@ -86,7 +99,7 @@ func (caller *Caller) CallChunked(opts *bind.CallOpts, chunkSize int, cooldown t
time.Sleep(cooldown)
}
chunk, err := caller.Call(opts, chunk...)
chunk, err := caller.calls(opts, chunk...)
if err != nil {
return calls, fmt.Errorf("call chunk [%d] failed: %v", i, err)
}