mirror of
https://github.com/forta-network/go-multicall.git
synced 2026-02-26 15:47:23 +00:00
Support single request
Outputs type supports nil
This commit is contained in:
parent
9467c4ddaa
commit
1fbee12081
3 changed files with 81 additions and 6 deletions
62
README.md
62
README.md
|
|
@ -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
10
call.go
|
|
@ -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)
|
||||
|
|
|
|||
15
caller.go
15
caller.go
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue