Skip to content

Commit 1d13ccd

Browse files
committed
Refactor ens and async_ens to call resolver only if coin_type is specified
1 parent aefb880 commit 1d13ccd

File tree

3 files changed

+103
-2
lines changed

3 files changed

+103
-2
lines changed

ens/async_ens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,12 @@ async def address(
152152
:param int coin_type: if provided, look up the address for this coin type
153153
:raises InvalidName: if `name` has invalid syntax
154154
"""
155-
r = await self.resolver(name)
156155
if coin_type is None:
157156
# don't validate `addr(bytes32)` interface id since extended resolvers
158157
# can implement a "resolve" function as of ENSIP-10
159158
return cast(ChecksumAddress, await self._resolve(name, "addr"))
160159
else:
160+
r = await self.resolver(name)
161161
await _async_validate_resolver_and_interface_id(
162162
name, r, ENS_MULTICHAIN_ADDRESS_INTERFACE_ID, "addr(bytes32,uint256)"
163163
)

ens/ens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,12 @@ def address(
154154
:raises UnsupportedFunction: if the resolver does not support the ``addr()``
155155
function
156156
"""
157-
r = self.resolver(name)
158157
if coin_type is None:
159158
# don't validate `addr(bytes32)` interface id since extended resolvers
160159
# can implement a "resolve" function as of ENSIP-10
161160
return cast(ChecksumAddress, self._resolve(name, "addr"))
162161
else:
162+
r = self.resolver(name)
163163
_validate_resolver_and_interface_id(
164164
name, r, ENS_MULTICHAIN_ADDRESS_INTERFACE_ID, "addr(bytes32,uint256)"
165165
)

tests/ens/test_ens.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import pytest
22
from unittest.mock import (
3+
AsyncMock,
4+
MagicMock,
35
patch,
46
)
57

@@ -10,6 +12,9 @@
1012
from ens._normalization import (
1113
normalize_name_ensip15,
1214
)
15+
from ens.utils import (
16+
raw_name_to_hash,
17+
)
1318
from web3 import (
1419
AsyncWeb3,
1520
)
@@ -143,6 +148,51 @@ def test_ens_methods_normalize_name(
143148
ens.setup_address("tester.eth", None)
144149

145150

151+
def test_ens_address_lookup_when_no_coin_type(ens):
152+
"""
153+
Test that when coin_type is None, the method calls _resolve(name, "addr")
154+
and returns the expected address.
155+
"""
156+
name = "tester.eth"
157+
address = ens.w3.eth.accounts[0]
158+
159+
with patch("ens.ENS.resolver") as mock_resolver_for_coin_types:
160+
with patch("ens.ENS._resolve") as mock_resolver:
161+
mock_resolver.return_value = address
162+
163+
returned_address = ens.address(name)
164+
165+
mock_resolver.assert_called_once_with(name, "addr")
166+
mock_resolver_for_coin_types.assert_not_called()
167+
assert returned_address == address
168+
169+
170+
def test_ens_address_lookup_with_coin_type(ens):
171+
"""
172+
Test that when coin_type is specified, it calls:
173+
1) _validate_resolver_and_interface_id
174+
2) resolver.caller.addr(node, coin_type)
175+
3) returns the checksum address
176+
"""
177+
name = "tester.eth"
178+
address = ens.w3.eth.accounts[0]
179+
coin_type = 60
180+
node = raw_name_to_hash(name)
181+
182+
mock_resolver = MagicMock()
183+
mock_resolver.caller.addr.return_value = address
184+
185+
with patch("ens.ENS.resolver") as resolver:
186+
resolver.return_value = mock_resolver
187+
188+
with patch("ens.ens._validate_resolver_and_interface_id") as mock_validate:
189+
returned_address = ens.address(name, coin_type=coin_type)
190+
191+
mock_validate.assert_called_once()
192+
mock_resolver.caller.addr.assert_called_once_with(node, coin_type)
193+
assert returned_address == address
194+
195+
146196
# -- async -- #
147197

148198

@@ -268,3 +318,54 @@ async def test_async_ens_methods_normalize_name_with_ensip15(
268318

269319
# cleanup
270320
await async_ens.setup_address("tester.eth", None)
321+
322+
323+
@pytest.mark.asyncio
324+
async def test_async_ens_address_lookup_when_no_coin_type(async_ens):
325+
"""
326+
Test that when coin_type is None, the method calls _resolve(name, "addr")
327+
and returns the expected address.
328+
"""
329+
name = "tester.eth"
330+
accounts = await async_ens.w3.eth.accounts
331+
address = accounts[2]
332+
333+
with patch("ens.AsyncENS.resolver") as mock_resolver_for_coin_types:
334+
with patch("ens.AsyncENS._resolve") as mock_resolver:
335+
mock_resolver.return_value = address
336+
337+
returned_address = await async_ens.address(name)
338+
339+
mock_resolver.assert_called_once_with(name, "addr")
340+
mock_resolver_for_coin_types.assert_not_called()
341+
assert returned_address == address
342+
343+
344+
@pytest.mark.asyncio
345+
async def test_async_ens_address_lookup_with_coin_type(async_ens):
346+
"""
347+
Test that when coin_type is specified, it calls:
348+
1) _async_validate_resolver_and_interface_id
349+
2) async resolver.caller.addr(node, coin_type)
350+
3) returns the checksum address
351+
"""
352+
name = "tester.eth"
353+
accounts = await async_ens.w3.eth.accounts
354+
address = accounts[2]
355+
coin_type = 60
356+
node = raw_name_to_hash(name)
357+
358+
mock_resolver = AsyncMock()
359+
mock_resolver.caller.addr.return_value = address
360+
361+
with patch("ens.AsyncENS.resolver") as resolver:
362+
resolver.return_value = mock_resolver
363+
364+
with patch(
365+
"ens.async_ens._async_validate_resolver_and_interface_id"
366+
) as mock_validate:
367+
returned_address = await async_ens.address(name, coin_type=coin_type)
368+
369+
mock_validate.assert_called_once()
370+
mock_resolver.caller.addr.assert_called_once_with(node, coin_type)
371+
assert returned_address == address

0 commit comments

Comments
 (0)