get ENS address from resolver rather than owner

pull/1174/head
James Sangalli 6 years ago
parent c6aeab2b9e
commit cf54ad1894
  1. 8
      AlphaWallet.xcodeproj/project.pbxproj
  2. 15
      AlphaWallet/RPC/Commands/web3swift-pod/GetENSInfoEncode.swift
  3. 10
      AlphaWallet/RPC/Commands/web3swift-pod/GetENSNameEncode.swift
  4. 2
      AlphaWallet/RPC/Commands/web3swift-pod/GetERC721BalanceEncode.swift
  5. 2
      AlphaWallet/RPC/Commands/web3swift-pod/GetERC875Balance.swift
  6. 2
      AlphaWallet/RPC/Commands/web3swift-pod/GetIsERC721Encode.swift
  7. 2
      AlphaWallet/RPC/Commands/web3swift-pod/GetIsERC875Encode.swift
  8. 39
      AlphaWallet/Tokens/Coordinators/GetENSOwnerCoordinator.swift
  9. 2
      AlphaWallet/Tokens/Coordinators/GetERC721BalanceCoordinator.swift
  10. 2
      AlphaWallet/Tokens/Coordinators/GetERC875BalanceCoordinator.swift
  11. 2
      AlphaWallet/Tokens/Coordinators/GetIsERC721ContractCoordinator.swift
  12. 2
      AlphaWallet/Tokens/Coordinators/GetIsERC875ContractCoordinator.swift
  13. 4
      AlphaWallet/UI/AddressTextField.swift
  14. 2
      AlphaWalletTests/Tokens/Coordinators/GetENSOwnerCoordinatorTests.swift

@ -540,7 +540,7 @@
76F1D7F08263A663C3A67926 /* GetIsERC721ContractCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76F1D4F77311FBF3A442E4B5 /* GetIsERC721ContractCoordinator.swift */; };
76F1D850F4F2E968CF8D9C86 /* MonkeyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B138ABCF208C2C93000FC28A /* MonkeyTest.swift */; };
76F1D91659771C9EEA7B48DC /* CreateRedeem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76F1DF80932454E9F58B7830 /* CreateRedeem.swift */; };
76F1D9BBB4ACAA00C8391172 /* GetENSNameEncode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76F1DC4B9964504DA12D8D3C /* GetENSNameEncode.swift */; };
76F1D9BBB4ACAA00C8391172 /* GetENSInfoEncode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76F1DC4B9964504DA12D8D3C /* GetENSInfoEncode.swift */; };
76F1DA1D816C1D6759FAAB5D /* ClaimNativeCurrencyOrder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76F1D00BB549E72210412062 /* ClaimNativeCurrencyOrder.swift */; };
76F1DB9E1443DCFC36228B08 /* ClaimOrderCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76F1D419EE36261E50ABAFAE /* ClaimOrderCoordinator.swift */; };
76F1DBCA8BAAA42BAEB14719 /* GetERC721BalanceCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76F1D473FF303828D93C95EB /* GetERC721BalanceCoordinator.swift */; };
@ -1161,7 +1161,7 @@
76F1DADFD07E2941897FD2E1 /* OrderHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrderHandler.swift; sourceTree = "<group>"; };
76F1DAFCBB43B6639472A229 /* BrowserHistoryViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrowserHistoryViewController.swift; sourceTree = "<group>"; };
76F1DB8034ACC2FC91F818F9 /* MyDappsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyDappsViewController.swift; sourceTree = "<group>"; };
76F1DC4B9964504DA12D8D3C /* GetENSNameEncode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetENSNameEncode.swift; sourceTree = "<group>"; };
76F1DC4B9964504DA12D8D3C /* GetENSInfoEncode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetENSInfoEncode.swift; sourceTree = "<group>"; };
76F1DCD54618349AC91C6DF8 /* UniversalLinkHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UniversalLinkHandler.swift; sourceTree = "<group>"; };
76F1DD09B44FD653C1500DA8 /* DappsHomeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DappsHomeViewController.swift; sourceTree = "<group>"; };
76F1DE7BEE799DDFB68D0F54 /* GetENSOwnerCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetENSOwnerCoordinator.swift; sourceTree = "<group>"; };
@ -2817,7 +2817,7 @@
5E7C7CA7D65743AEE3411F3A /* GetIsERC721Encode.swift */,
5E7C7DCB0BDDD30D10130AE7 /* GetIsERC875Encode.swift */,
5E7C72CD0C22247A6AF7C95E /* GetERC721BalanceEncode.swift */,
76F1DC4B9964504DA12D8D3C /* GetENSNameEncode.swift */,
76F1DC4B9964504DA12D8D3C /* GetENSInfoEncode.swift */,
5E7C787CA216AFED8023A35F /* CallForAssetAttribute.swift */,
);
path = "web3swift-pod";
@ -4038,7 +4038,7 @@
5E7C7E7AEF01B9D170228342 /* TimeEntryField.swift in Sources */,
5E7C7719948721FE9120B5B2 /* PeekOpenSeaNonFungibleTokenViewController.swift in Sources */,
76F1D5ECC391A932C96CAC13 /* GetENSOwnerCoordinator.swift in Sources */,
76F1D9BBB4ACAA00C8391172 /* GetENSNameEncode.swift in Sources */,
76F1D9BBB4ACAA00C8391172 /* GetENSInfoEncode.swift in Sources */,
5E7C73CA81FB2CE9BCAFC992 /* CallForAssetAttribute.swift in Sources */,
5E7C77552A957D1B144D9209 /* CallForAssetAttributeCoordinator.swift in Sources */,
5E7C7C8BC4763CFDD3EE119D /* AssetAttributeFunctionCall.swift in Sources */,

@ -0,0 +1,15 @@
//
// Created by James Sangalli on 8/11/18.
//
import Foundation
struct GetENSResolverEncode {
let abi = "[ { \"constant\": false, \"inputs\": [ { \"name\": \"node\", \"type\": \"bytes32\" } ], \"name\": \"resolver\", \"outputs\": [ { \"name\": \"\", \"type\": \"address\" } ], \"payable\": false, \"stateMutability\": \"nonpayable\", \"type\": \"function\" } ]"
let name = "resolver"
}
struct GetENSRecordFromResolverEncode {
let abi = "[ { \"constant\": false, \"inputs\": [ { \"name\": \"node\", \"type\": \"bytes32\" } ], \"name\": \"addr\", \"outputs\": [ { \"name\": \"\", \"type\": \"address\" } ], \"payable\": false, \"stateMutability\": \"nonpayable\", \"type\": \"function\" } ]"
let name = "addr"
}

@ -1,10 +0,0 @@
//
// Created by James Sangalli on 8/11/18.
//
import Foundation
struct GetENSOwnerEncode {
let abi = "{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"}"
let name = "owner"
}

@ -6,6 +6,6 @@
import Foundation
struct GetERC721Balance {
let abi = "{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}"
let abi = "[{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]"
let name = "balanceOf"
}

@ -2,6 +2,6 @@ import Foundation
import TrustKeystore
struct GetERC875Balance {
let abi = "{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}"
let abi = "[{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]"
let name = "balanceOf"
}

@ -6,6 +6,6 @@
import Foundation
struct GetIsERC721 {
let abi = "{ \"constant\": true, \"inputs\": [ { \"name\": \"interfaceID\", \"type\": \"bytes4\" } ], \"name\": \"supportsInterface\", \"outputs\": [ { \"name\": \"\", \"type\": \"bool\" } ], \"payable\": false, \"stateMutability\": \"view\", \"type\": \"function\" }"
let abi = "[{ \"constant\": true, \"inputs\": [ { \"name\": \"interfaceID\", \"type\": \"bytes4\" } ], \"name\": \"supportsInterface\", \"outputs\": [ { \"name\": \"\", \"type\": \"bool\" } ], \"payable\": false, \"stateMutability\": \"view\", \"type\": \"function\" }]"
let name = "supportsInterface"
}

@ -3,6 +3,6 @@
import Foundation
struct GetIsERC875 {
let abi = "{\"constant\":true,\"inputs\":[],\"name\":\"isStormBirdContract\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}"
let abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"isStormBirdContract\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]"
let name = "isStormBirdContract"
}

@ -21,7 +21,7 @@ extension String {
}
}
class GetENSOwnerCoordinator {
class GetENSAddressCoordinator {
private struct ENSLookupKey: Hashable {
let name: String
let server: RPCServer
@ -37,7 +37,7 @@ class GetENSOwnerCoordinator {
self.server = server
}
func getENSOwner(
func getENSAddressFromResolver(
for input: String,
completion: @escaping (Result<EthereumAddress, AnyError>) -> Void
) {
@ -60,21 +60,34 @@ class GetENSOwnerCoordinator {
return
}
let function = GetENSOwnerEncode()
let function = GetENSResolverEncode()
guard let ensRegistrarContract = Address(string: server.ensRegistrarContract.address) else {
completion(.failure(AnyError(Web3Error(description: "Error converting contract address: \(server.ensRegistrarContract.address)"))))
return
}
callSmartContract(withServer: server, contract: ensRegistrarContract, functionName: function.name, abiString: "[\(function.abi)]", parameters: [node] as [AnyObject]).done { result in
callSmartContract(withServer: server, contract: ensRegistrarContract, functionName: function.name, abiString: function.abi, parameters: [node] as [AnyObject]).done { result in
//if null address is returned (as 0) we count it as invalid
//this is because it is not assigned to an ENS and puts the user in danger of sending funds to null
if let owner = result["0"] as? EthereumAddress {
if owner.address == Constants.nullAddress {
if let resolver = result["0"] as? EthereumAddress {
if resolver.address == Constants.nullAddress {
completion(.failure(AnyError(Web3Error(description: "Null address returned"))))
} else {
//Retain self because it's useful to cache the results even if we don't immediately need it now
self.cache(forNode: node, result: owner)
completion(.success(owner))
let function = GetENSRecordFromResolverEncode()
//TODO remove Address as a type because EthereumAddress co-exists or vice versa
callSmartContract(withServer: self.server, contract: Address(string: resolver.address)!, functionName: function.name, abiString: function.abi, parameters: [node] as [AnyObject]).done { result in
if let ensAddress = result["0"] as? EthereumAddress {
if ensAddress.address == Constants.nullAddress {
completion(.failure(AnyError(Web3Error(description: "Null address returned"))))
} else {
//Retain self because it's useful to cache the results even if we don't immediately need it now
self.cache(forNode: node, result: ensAddress)
completion(.success(ensAddress))
}
} else {
completion(.failure(AnyError(Web3Error(description: "Incorrect data output from ENS resolver"))))
}
}
}
} else {
completion(.failure(AnyError(Web3Error(description: "Error extracting result from \(ensRegistrarContract).\(function.name)()"))))
@ -92,19 +105,19 @@ class GetENSOwnerCoordinator {
}
toStartResolvingEnsNameTimer?.invalidate()
toStartResolvingEnsNameTimer = Timer.scheduledTimer(withTimeInterval: GetENSOwnerCoordinator.DELAY_AFTER_STOP_TYPING_TO_START_RESOLVING_ENS_NAME, repeats: false) { _ in
toStartResolvingEnsNameTimer = Timer.scheduledTimer(withTimeInterval: GetENSAddressCoordinator.DELAY_AFTER_STOP_TYPING_TO_START_RESOLVING_ENS_NAME, repeats: false) { _ in
//Retain self because it's useful to cache the results even if we don't immediately need it now
self.getENSOwner(for: input) { result in
self.getENSAddressFromResolver(for: input) { result in
completion(result)
}
}
}
private func cachedResult(forNode node: String) -> EthereumAddress? {
return GetENSOwnerCoordinator.resultsCache[ENSLookupKey(name: node, server: server)]
return GetENSAddressCoordinator.resultsCache[ENSLookupKey(name: node, server: server)]
}
private func cache(forNode node: String, result: EthereumAddress) {
GetENSOwnerCoordinator.resultsCache[ENSLookupKey(name: node, server: server)] = result
GetENSAddressCoordinator.resultsCache[ENSLookupKey(name: node, server: server)] = result
}
}

@ -21,7 +21,7 @@ class GetERC721BalanceCoordinator {
completion: @escaping (Result<BigUInt, AnyError>) -> Void
) {
let function = GetERC721Balance()
callSmartContract(withServer: server, contract: contract, functionName: function.name, abiString: "[\(function.abi)]", parameters: [address.eip55String] as [AnyObject]).done { balanceResult in
callSmartContract(withServer: server, contract: contract, functionName: function.name, abiString: function.abi, parameters: [address.eip55String] as [AnyObject]).done { balanceResult in
let balance = self.adapt(balanceResult["0"])
completion(.success(balance))
}.catch { error in

@ -17,7 +17,7 @@ class GetERC875BalanceCoordinator {
completion: @escaping (Result<[String], AnyError>) -> Void
) {
let function = GetERC875Balance()
callSmartContract(withServer: server, contract: contract, functionName: function.name, abiString: "[\(function.abi)]", parameters: [address.eip55String] as [AnyObject]).done { balanceResult in
callSmartContract(withServer: server, contract: contract, functionName: function.name, abiString: function.abi, parameters: [address.eip55String] as [AnyObject]).done { balanceResult in
let balances = self.adapt(balanceResult["0"])
completion(.success(balances))
}.catch {

@ -54,7 +54,7 @@ class GetIsERC721ContractCoordinator {
let web3 = web3swift.web3(provider: webProvider)
let function = GetIsERC721()
guard let contractInstance = web3swift.web3.web3contract(web3: web3, abiString: "[\(function.abi)]", at: contractAddress, options: web3.options) else {
guard let contractInstance = web3swift.web3.web3contract(web3: web3, abiString: function.abi, at: contractAddress, options: web3.options) else {
completion(.failure(AnyError(Web3Error(description: "Error creating web3swift contract instance to call \(function.name)()"))))
return
}

@ -16,7 +16,7 @@ class GetIsERC875ContractCoordinator {
completion: @escaping (Result<Bool, AnyError>) -> Void
) {
let function = GetIsERC875()
callSmartContract(withServer: server, contract: contract, functionName: function.name, abiString: "[\(function.abi)]").done { dictionary in
callSmartContract(withServer: server, contract: contract, functionName: function.name, abiString: function.abi).done { dictionary in
if let isERC875 = dictionary["0"] as? Bool {
completion(.success(isERC875))
} else {

@ -149,7 +149,7 @@ class AddressTextField: UIControl {
return
} else {
textField.text = value
GetENSOwnerCoordinator(server: serverToResolveEns).getENSOwner(for: value) { result in
GetENSAddressCoordinator(server: serverToResolveEns).getENSAddressFromResolver(for: value) { result in
guard let address = result.value else {
//Don't show an error when pasting what seems like a wrong ENS name for better usability
return
@ -171,7 +171,7 @@ class AddressTextField: UIControl {
private func queueResolution(ofValue value: String) {
let value = value.trimmed
let oldTextValue = textField.text?.trimmed
GetENSOwnerCoordinator(server: serverToResolveEns).queueGetENSOwner(for: value) { [weak self] result in
GetENSAddressCoordinator(server: serverToResolveEns).queueGetENSOwner(for: value) { [weak self] result in
guard let strongSelf = self else { return }
if let address = result.value {
guard CryptoAddressValidator.isValidAddress(address.address) else {

@ -17,7 +17,7 @@ class GetENSOwnerCoordinatorTests: XCTestCase {
expectations.append(expectation)
let ensName = "b00n.thisisme.eth"
let server = makeServerForMainnet()
GetENSOwnerCoordinator(server: server).getENSOwner(for: ensName) { result in
GetENSAddressCoordinator(server: server).getENSAddressFromResolver(for: ensName) { result in
if let address = result.value, address.address.sameContract(as: "0xbbce83173d5c1D122AE64856b4Af0D5AE07Fa362") {
expectation.fulfill()
}

Loading…
Cancel
Save