由于web3swift库并不完善,单元测试中缺少“addr”方法,而本人开发过程中又需要用到,即:将ENS域名转成16进制地址;于是特地写了篇文章作为记录,希望有同样需求的同鞋能用上。
首先要引入web3swift库,地址:https://github.com/BANKEX/web3swift
//MARK:将ENS域名转成16进制地址字符串
func keccakHexStringFromENSString (inputName: String) -> String {
var node = ""
for _ in 0..<32 {
node += "00"
}
let name = normalize(name: inputName)
if name.count > 0 {
//将字符串用“.”分割成数组并将数组倒序
var labels = name.split(separator: ".")
labels.reverse()
//递归
for subLabels in labels {
let str = String(subLabels)
var labbelSha = str.sha3(.keccak256)
labbelSha = "0x" + node + labbelSha
let data = convertToData(labbelSha as AnyObject)
node = (data?.sha3(.keccak256).toHexString())!
print("0x" + node)
}
}
return infuratestResolver(encodeStr: "0x" + node)
}
//将某类型转成Data
func convertToData(_ value: AnyObject) -> Data? {
switch value {
case let d as Data:
return d
case let d as String:
if d.hasHexPrefix() {
let hex = Data.fromHex(d)
if hex != nil {
return hex
}
}
let str = d.data(using: .utf8)
if str != nil {
return str
}
case let d as [UInt8]:
return Data(d)
case let d as EthereumAddress:
return d.addressData
case let d as [IntegerLiteralType]:
var bytesArray = [UInt8]()
for el in d {
guard el >= 0, el <= 255 else {return nil}
bytesArray.append(UInt8(el))
}
return Data(bytesArray)
default:
return nil
}
return nil
}
func normalize(name: String) -> String {
var lastName = name.trimmingCharacters(in: .whitespaces)
//判断表情的正则表达式,并把表情替换为空
let pattern = "[\\ud83c\\udc00-\\ud83c\\udfff]|[\\ud83d\\udc00-\\ud83d\\udfff]|[\\u2600-\\u27ff]"
lastName = lastName.pregReplace(pattern: pattern, with: "")
return lastName
}
//执行"addr"方法
func infuratestResolver(encodeStr: String) -> String {
let jsonString = "[{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"contentTypes\",\"type\":\"uint256\"}],\"name\":\"ABI\",\"outputs\":[{\"name\":\"contentType\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"x\",\"type\":\"bytes32\"},{\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"setPubkey\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"content\",\"outputs\":[{\"name\":\"ret\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"name\":\"ret\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"contentType\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"setABI\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"name\":\"ret\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"setContent\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"pubkey\",\"outputs\":[{\"name\":\"x\",\"type\":\"bytes32\"},{\"name\":\"y\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"ensAddr\",\"type\":\"address\"}],\"payable\":false,\"type\":\"constructor\"},{\"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\":false,\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"ContentChanged\",\"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\":\"contentType\",\"type\":\"uint256\"}],\"name\":\"ABIChanged\",\"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\"}]"
do {
let web3 = Web3.InfuraMainnetWeb3()
let constractAddress = EthereumAddress("0x1da022710dF5002339274AaDEe8D58218e9D6AB5")
var options = Web3Options.defaultOptions()
options.to = constractAddress
options.from = constractAddress
let parametersCall = [encodeStr] as [AnyObject]
let contract = web3.contract(jsonString, at: constractAddress, abiVersion: 2)!
let transaction = contract.method("addr", parameters:parametersCall, options: options)
guard let tokenNameRes = transaction?.call(options: options) else {return ""}
guard case .success(let result) = tokenNameRes else {return ""}
if result.isEmpty {
return ""
}else {
let dictValuesArray = [Any](result.values)
if dictValuesArray.count > 0 {
let addr: EthereumAddress = dictValuesArray[0] as! EthereumAddress
return addr.address
}else {
return ""
}
}
} catch {
XCTFail()
print(error)
return ""
}
}
//测试
func testABI() {
let ENSString = keccakHexStringFromENSString(inputName: "linktime.eth")
print(ENSString)
}