mirror of
https://github.com/forta-network/go-multicall.git
synced 2026-02-26 07:37:23 +00:00
fix chunking
This commit is contained in:
parent
83a1516841
commit
1436386c67
2 changed files with 84 additions and 10 deletions
40
caller.go
40
caller.go
|
|
@ -78,21 +78,41 @@ func (caller *Caller) Call(opts *bind.CallOpts, calls ...*Call) ([]*Call, error)
|
|||
|
||||
// CallChunked makes multiple multicalls by chunking given calls.
|
||||
func (caller *Caller) CallChunked(opts *bind.CallOpts, chunkSize int, calls ...*Call) ([]*Call, error) {
|
||||
if chunkSize <= 0 || len(calls) < 2 {
|
||||
return caller.Call(opts, calls...)
|
||||
}
|
||||
callCount := len(calls) / chunkSize
|
||||
|
||||
var allCalls []*Call
|
||||
for i := 0; i < callCount; i++ {
|
||||
start := i * chunkSize
|
||||
end := start + chunkSize
|
||||
chunk, err := caller.Call(opts, calls[start:end]...)
|
||||
for i, chunk := range chunkInputs(chunkSize, calls) {
|
||||
chunk, err := caller.Call(opts, chunk...)
|
||||
if err != nil {
|
||||
return calls, fmt.Errorf("call chunk [%d] failed: %v", i, err)
|
||||
}
|
||||
allCalls = append(allCalls, chunk...)
|
||||
}
|
||||
|
||||
return allCalls, nil
|
||||
}
|
||||
|
||||
func chunkInputs[T any](chunkSize int, inputs []T) (chunks [][]T) {
|
||||
if len(inputs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if chunkSize <= 0 || len(inputs) < 2 || chunkSize > len(inputs) {
|
||||
return [][]T{inputs}
|
||||
}
|
||||
|
||||
lastChunkSize := len(inputs) % chunkSize
|
||||
|
||||
chunkCount := len(inputs) / chunkSize
|
||||
|
||||
for i := 0; i < chunkCount; i++ {
|
||||
start := i * chunkSize
|
||||
end := start + chunkSize
|
||||
chunks = append(chunks, inputs[start:end])
|
||||
}
|
||||
|
||||
if lastChunkSize > 0 {
|
||||
start := chunkCount * chunkSize
|
||||
end := start + lastChunkSize
|
||||
chunks = append(chunks, inputs[start:end])
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -325,3 +325,57 @@ func TestDial(t *testing.T) {
|
|||
r.NoError(err)
|
||||
r.NotNil(caller)
|
||||
}
|
||||
|
||||
func TestChunkInputs(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
chunkSize int
|
||||
inputs []int
|
||||
expected [][]int
|
||||
}{
|
||||
{
|
||||
name: "zero inputs large chunk size",
|
||||
chunkSize: 12345,
|
||||
inputs: []int{},
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
name: "single input large chunk size",
|
||||
chunkSize: 12345,
|
||||
inputs: []int{10},
|
||||
expected: [][]int{{10}},
|
||||
},
|
||||
{
|
||||
name: "2 inputs chunk size 1",
|
||||
chunkSize: 1,
|
||||
inputs: []int{10, 20},
|
||||
expected: [][]int{{10}, {20}},
|
||||
},
|
||||
{
|
||||
name: "2 inputs chunk size 2",
|
||||
chunkSize: 2,
|
||||
inputs: []int{10, 20},
|
||||
expected: [][]int{{10, 20}},
|
||||
},
|
||||
{
|
||||
name: "5 inputs chunk size 3",
|
||||
chunkSize: 3,
|
||||
inputs: []int{10, 20, 30, 40, 50},
|
||||
expected: [][]int{{10, 20, 30}, {40, 50}},
|
||||
},
|
||||
{
|
||||
name: "3 inputs chunk size 5",
|
||||
chunkSize: 5,
|
||||
inputs: []int{10, 20, 30},
|
||||
expected: [][]int{{10, 20, 30}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
r := require.New(t)
|
||||
|
||||
r.Equal(testCase.expected, chunkInputs(testCase.chunkSize, testCase.inputs))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue