From 2f617964dc9b4b5128f061a76313896a6d18daac Mon Sep 17 00:00:00 2001 From: Mark Barrasso Date: Tue, 30 Apr 2019 18:59:25 -0700 Subject: [PATCH 1/3] Add new resolver ABI Changed old resolver ABI to `legacyResolverABI`. Added new resolver ABI -> https://ropsten.etherscan.io/address/0x44385b20865fe3578e56aa0e9f7ec534deb10501#code --- Sources/web3swift/Web3/Web3+Utils.swift | 557 +++++++++++++++++++++++- 1 file changed, 556 insertions(+), 1 deletion(-) diff --git a/Sources/web3swift/Web3/Web3+Utils.swift b/Sources/web3swift/Web3/Web3+Utils.swift index 5c079f1f4..47faa4bbc 100755 --- a/Sources/web3swift/Web3/Web3+Utils.swift +++ b/Sources/web3swift/Web3/Web3+Utils.swift @@ -4887,7 +4887,7 @@ extension Web3.Utils { """ //function setAddr(bytes32 node, address addr) - public static var resolverABI = """ + public static var legacyResolverABI = """ [ { "constant": true, @@ -5336,6 +5336,561 @@ extension Web3.Utils { "type": "event" } ] +""" + + public static var resolverABI = """ +[ + { + "constant": true, + "inputs": + [ + { + "name": "interfaceID", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": + [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": false, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "key", + "type": "string" + }, + { + "name": "value", + "type": "string" + } + ], + "name": "setText", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "interfaceID", + "type": "bytes4" + } + ], + "name": "interfaceImplementer", + "outputs": + [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "contentTypes", + "type": "uint256" + } + ], + "name": "ABI", + "outputs": + [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "x", + "type": "bytes32" + }, + { + "name": "y", + "type": "bytes32" + } + ], + "name": "setPubkey", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "hash", + "type": "bytes" + } + ], + "name": "setContenthash", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "addr", + "outputs": + [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "key", + "type": "string" + } + ], + "name": "text", + "outputs": + [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "contentType", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + } + ], + "name": "setABI", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "name", + "outputs": + [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "name", + "type": "string" + } + ], + "name": "setName", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": + [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isOwner", + "outputs": + [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "contenthash", + "outputs": + [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "pubkey", + "outputs": + [ + { + "name": "x", + "type": "bytes32" + }, + { + "name": "y", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "addr", + "type": "address" + } + ], + "name": "setAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": + [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "interfaceID", + "type": "bytes4" + }, + { + "name": "implementer", + "type": "address" + } + ], + "name": "setInterface", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": + [ + { + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": true, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "indexedKey", + "type": "string" + }, + { + "indexed": false, + "name": "key", + "type": "string" + } + ], + "name": "TextChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": true, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "x", + "type": "bytes32" + }, + { + "indexed": false, + "name": "y", + "type": "bytes32" + } + ], + "name": "PubkeyChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": true, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "name", + "type": "string" + } + ], + "name": "NameChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": true, + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "name": "interfaceID", + "type": "bytes4" + }, + { + "indexed": false, + "name": "implementer", + "type": "address" + } + ], + "name": "InterfaceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": true, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "hash", + "type": "bytes" + } + ], + "name": "ContenthashChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": true, + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "name": "a", + "type": "address" + } + ], + "name": "AddrChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": true, + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "name": "contentType", + "type": "uint256" + } + ], + "name": "ABIChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": + [ + { + "indexed": true, + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + } +] """ } From c0719155cce64d8c0b6c4816f8d083030851a39a Mon Sep 17 00:00:00 2001 From: Mark Barrasso Date: Tue, 30 Apr 2019 19:18:32 -0700 Subject: [PATCH 2/3] Add interfaceImplementer function Added `interfaceImplementer` function found in the new [OwnedResolver](https://ropsten.etherscan.io/address/0x44385b20865fe3578e56aa0e9f7ec534deb10501#code). ### Usage ```swift public enum InterfaceID: String { case legacyRegistrar = "0x7ba18ba1" case permanentRegistrar = "0x018fac06" case baseRegistrar = "0x6ccb2df4" } // Get the ETHRegistrarController's address let controller = try! e.resolver?.interfaceImplementer(forNode: "eth", interfaceID: InterfaceID.permanentRegistrar.rawValue) ``` See more usage at: https://github.com/ensdomains/ens-app/blob/d79a4f5a8231e46743caa19d0368fff9fe237383/src/api/registrar.js#L94 --- Sources/web3swift/Utils/ENS/ENSResolver.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Sources/web3swift/Utils/ENS/ENSResolver.swift b/Sources/web3swift/Utils/ENS/ENSResolver.swift index 6cee1177a..8f674dfe8 100755 --- a/Sources/web3swift/Utils/ENS/ENSResolver.swift +++ b/Sources/web3swift/Utils/ENS/ENSResolver.swift @@ -19,7 +19,7 @@ public extension ENS { case CBOR = 4 case URI = 8 } - + public enum InterfaceName { case addr case name @@ -72,6 +72,14 @@ public extension ENS { guard let supports = result["0"] as? Bool else {throw Web3Error.processingError(desc: "Can't get answer")} return supports } + + public func interfaceImplementer(forNode node: String, interfaceID: InterfaceID) throws -> EthereumAddress { + guard let nameHash = NameHash.nameHash(node) else {throw Web3Error.processingError(desc: "Failed to get name hash")} + guard let transaction = self.resolverContract.read("interfaceImplementer", parameters: [nameHash, interfaceID] as [AnyObject], extraData: Data(), transactionOptions: defaultOptions) else {throw Web3Error.transactionSerializationError} + guard let result = try? transaction.call(transactionOptions: defaultOptions) else {throw Web3Error.processingError(desc: "Can't call transaction")} + guard let address = result["0"] as? EthereumAddress else {throw Web3Error.processingError(desc: "Can't get address")} + return address + } public func getAddress(forNode node: String) throws -> EthereumAddress { guard let nameHash = NameHash.nameHash(node) else {throw Web3Error.processingError(desc: "Failed to get name hash")} From 5ab6a9db038933740042d2a9d106e73e7c79253f Mon Sep 17 00:00:00 2001 From: Mark Barrasso Date: Tue, 30 Apr 2019 19:40:48 -0700 Subject: [PATCH 3/3] Update ENSResolver.swift --- Sources/web3swift/Utils/ENS/ENSResolver.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/web3swift/Utils/ENS/ENSResolver.swift b/Sources/web3swift/Utils/ENS/ENSResolver.swift index 8f674dfe8..67176af8d 100755 --- a/Sources/web3swift/Utils/ENS/ENSResolver.swift +++ b/Sources/web3swift/Utils/ENS/ENSResolver.swift @@ -73,7 +73,7 @@ public extension ENS { return supports } - public func interfaceImplementer(forNode node: String, interfaceID: InterfaceID) throws -> EthereumAddress { + public func interfaceImplementer(forNode node: String, interfaceID: String) throws -> EthereumAddress { guard let nameHash = NameHash.nameHash(node) else {throw Web3Error.processingError(desc: "Failed to get name hash")} guard let transaction = self.resolverContract.read("interfaceImplementer", parameters: [nameHash, interfaceID] as [AnyObject], extraData: Data(), transactionOptions: defaultOptions) else {throw Web3Error.transactionSerializationError} guard let result = try? transaction.call(transactionOptions: defaultOptions) else {throw Web3Error.processingError(desc: "Can't call transaction")}