From 92034e9b15db6ed8d2ce60b1b56a67499ffc8bd4 Mon Sep 17 00:00:00 2001 From: banteg Date: Tue, 28 Jan 2020 16:56:46 +0700 Subject: [PATCH] add multicall --- multicall/constants.py | 2 +- multicall/multicall.py | 23 +++++++++++++++++++++++ tests/test_multicall.py | 21 +++++++++++++++++++++ tests/test_signature.py | 2 +- 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 multicall/multicall.py create mode 100644 tests/test_multicall.py diff --git a/multicall/constants.py b/multicall/constants.py index e4144fd..95be8b6 100644 --- a/multicall/constants.py +++ b/multicall/constants.py @@ -9,7 +9,7 @@ class Network(IntEnum): xDai = 100 -MULTICALL_ADDRESS = { +MULTICALL_ADDRESSES = { Network.Mainnet: '0xeefBa1e63905eF1D7ACbA5a8513c70307C1cE441', Network.Kovan: '0x2cc8688C5f75E365aaEEb4ea8D6a480405A48D2A', Network.Rinkeby: '0x42Ad527de7d4e9d9d011aC45B31D8551f8Fe9821', diff --git a/multicall/multicall.py b/multicall/multicall.py new file mode 100644 index 0000000..ba856aa --- /dev/null +++ b/multicall/multicall.py @@ -0,0 +1,23 @@ +from typing import List + +from web3.auto import w3 + +from multicall import Call +from multicall.constants import MULTICALL_ADDRESSES + + +class Multicall: + def __init__(self, calls: List[Call]): + self.calls = calls + + def __call__(self): + aggregate = Call( + MULTICALL_ADDRESSES[w3.eth.chainId], + 'aggregate((address,bytes)[])(uint256,bytes[])', + ) + args = [[[call.target, call.data] for call in self.calls]] + block, outputs = aggregate(args) + result = {} + for call, output in zip(self.calls, outputs): + result.update(call.decode_output(output)) + return result diff --git a/tests/test_multicall.py b/tests/test_multicall.py new file mode 100644 index 0000000..c115a6c --- /dev/null +++ b/tests/test_multicall.py @@ -0,0 +1,21 @@ +from multicall import Call, Multicall + +CHAI = '0x06AF07097C9Eeb7fD685c692751D5C66dB49c215' + + +def from_wei(val): + return val / 1e18 + + +def from_ray(val): + return val / 1e27 + + +def test_multicall(): + multi = Multicall([ + Call(CHAI, 'totalSupply()(uint256)', [['supply', from_wei]]), + Call(CHAI, ['balanceOf(address)(uint256)', CHAI], [['balance', from_ray]]), + ]) + result = multi() + assert isinstance(result['supply'], float) + assert isinstance(result['balance'], float) diff --git a/tests/test_signature.py b/tests/test_signature.py index 082ef74..e37c1a4 100644 --- a/tests/test_signature.py +++ b/tests/test_signature.py @@ -1,4 +1,4 @@ -from eth_abi import encode_abi, decode_abi +from eth_abi import encode_abi from multicall import Signature args = ((1, 2, 3), '0x' + 'f' * 40, b'data')