mirror of
https://github.com/forta-network/go-multicall.git
synced 2026-06-07 07:28:41 +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!)
|
(See other examples under the `examples` directory!)
|
||||||
|
|
||||||
|
#### Multicall
|
||||||
```go
|
```go
|
||||||
package main
|
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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
|
@ -80,15 +79,16 @@ func (call *Call) Unpack(b []byte) error {
|
||||||
if t.Kind() == reflect.Pointer {
|
if t.Kind() == reflect.Pointer {
|
||||||
t = t.Elem()
|
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)
|
out, err := call.Contract.ABI.Unpack(call.Method, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to unpack '%s' outputs: %v", call.Method, err)
|
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()
|
fieldCount := t.NumField()
|
||||||
for i := 0; i < fieldCount; i++ {
|
for i := 0; i < fieldCount; i++ {
|
||||||
field := t.Field(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.
|
// Call makes multicalls.
|
||||||
func (caller *Caller) Call(opts *bind.CallOpts, calls ...*Call) ([]*Call, error) {
|
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
|
var multiCalls []contract_multicall.Multicall3Call3
|
||||||
|
|
||||||
for i, call := range calls {
|
for i, call := range calls {
|
||||||
|
|
@ -86,7 +99,7 @@ func (caller *Caller) CallChunked(opts *bind.CallOpts, chunkSize int, cooldown t
|
||||||
time.Sleep(cooldown)
|
time.Sleep(cooldown)
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk, err := caller.Call(opts, chunk...)
|
chunk, err := caller.calls(opts, chunk...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return calls, fmt.Errorf("call chunk [%d] failed: %v", i, err)
|
return calls, fmt.Errorf("call chunk [%d] failed: %v", i, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue