Skip to content

Commit fa43d40

Browse files
committed
Add support and tests for reverse resolving
1 parent f283dd4 commit fa43d40

File tree

5 files changed

+42
-0
lines changed

5 files changed

+42
-0
lines changed

Sources/ENSKit/ENSKit.swift

+9
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ public struct ENSKit {
5757
return nil
5858
}
5959

60+
public func name(addr: String) async -> String? {
61+
let reversedDomain = addr.lowercased().replacingOccurrences(of: "0x", with: "") + ".addr.reverse"
62+
if let resolver = try? await resolver(name: reversedDomain),
63+
let name = try? await resolver.name() {
64+
return name
65+
}
66+
return nil
67+
}
68+
6069
public func text(name: String, key: String) async -> String? {
6170
if let resolver = try? await resolver(name: name),
6271
let text = try? await resolver.text(key: key) {

Sources/ENSKit/ENSResolver.swift

+7
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ public struct ENSResolver {
3434
return nil
3535
}
3636

37+
public func name() async throws -> String? {
38+
if let name: String = try await resolver.name(namehash: namehash) {
39+
return name
40+
}
41+
return nil
42+
}
43+
3744
public func avatar() async throws -> Data? {
3845
if let avatar = try await getAvatar(),
3946
let url = try await getAvatarImageURL(from: avatar),

Sources/ENSKit/EthereumContract/PublicResolverContract.swift

+13
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ struct PublicResolverContract: BaseContract {
88
var interfaces = [
99
"supportsInterface": "01ffc9a7", // supportsInterface(bytes4)
1010
"addr": "3b3b57de", // addr(bytes32)
11+
"name": "691f3431", // name(bytes32)
1112
"text": "59d1d43c", // text(bytes32,string)
1213
"contenthash": "bc1c58d1" // contenthash(bytes32)
1314
]
@@ -42,6 +43,18 @@ struct PublicResolverContract: BaseContract {
4243
return nil
4344
}
4445

46+
func name(namehash: Data) async throws -> String? {
47+
let data = "0x" + interfaces["name"]! + ContractEncoder.bytes(namehash)
48+
let result = try await ethCall(data)
49+
let s = result.stringValue
50+
if let (at, _) = ContractDecoder.int(s),
51+
let name = ContractDecoder.string(s, at: at),
52+
!name.isEmpty {
53+
return name
54+
}
55+
return nil
56+
}
57+
4558
func addrChangedEvents(namehash: Data) async throws -> [ContractEvent] {
4659
let namehashTopic = "0x" + ContractEncoder.bytes(namehash)
4760
let result = try await ethGetLogs(topics: [

Tests/ENSKitTests/ENSKitTests.swift

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ final class ENSKitTests: XCTestCase {
4545
XCTAssertEqual(vitalikAddr, "d8dA6BF26964aF9D7eEd9e03E53415D37aA96045")
4646
}
4747

48+
func testName() async throws {
49+
let vitalikName = await main.name(addr: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")
50+
XCTAssertEqual(vitalikName, "vitalik.eth")
51+
}
52+
4853
func testText() async throws {
4954
let coaEmail = await main.text(name: "coa.eth", key: "email")
5055
XCTAssertEqual(coaEmail, "[email protected]")

Tests/ENSKitTests/EthereumContractTests/PublicResolverContractTests.swift

+8
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ final class PublicResolverContractTests: XCTestCase {
55
// Test against .eth public resolver with Infura Ethereum API (please do not abuse my project id)
66
let client = InfuraEthereumAPI(url: URL(string: "https://mainnet.infura.io/v3/4cd2c3b40ea8423fa889fc479e05f082")!)
77
let resolverAddress = try! Address("0x4976fb03c32e5b8cfe2b6ccb31c09ba78ebaba41")
8+
let reverseResolverAddress: Address = try! Address("0x5fbb459c49bb06083c33109fa4f14810ec2cf358")
89
let vitalik = Namehash.namehash("vitalik.eth")
910
let planetable = Namehash.namehash("planetable.eth")
11+
let vitalikAddressReversed = Namehash.namehash("d8da6bf26964af9d7eed9e03e53415d37aa96045.addr.reverse")
1012

1113
func testSupportsInterface() async throws {
1214
let contract = PublicResolverContract(client: client, address: resolverAddress)
@@ -28,6 +30,12 @@ final class PublicResolverContractTests: XCTestCase {
2830
XCTAssertEqual(vitalikAddress!, try! Address("0xd8da6bf26964af9d7eed9e03e53415d37aa96045"))
2931
}
3032

33+
func testName() async throws {
34+
let contract = PublicResolverContract(client: client, address: reverseResolverAddress)
35+
let vitalikDomain = try await contract.name(namehash: vitalikAddressReversed)
36+
XCTAssertEqual(vitalikDomain!, "vitalik.eth")
37+
}
38+
3139
func testContentHash() async throws {
3240
let contract = PublicResolverContract(client: client, address: resolverAddress)
3341
let planetableContentHash = try await contract.contenthash(namehash: planetable)

0 commit comments

Comments
 (0)