diff --git a/web3swift.xcodeproj/project.pbxproj b/web3swift.xcodeproj/project.pbxproj index 024180735..9597e5962 100755 --- a/web3swift.xcodeproj/project.pbxproj +++ b/web3swift.xcodeproj/project.pbxproj @@ -81,8 +81,6 @@ 8159C50B21352CB700197B91 /* Web3+ERC20.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8159C50A21352CB700197B91 /* Web3+ERC20.swift */; }; 8159C50C21352CB700197B91 /* Web3+ERC20.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8159C50A21352CB700197B91 /* Web3+ERC20.swift */; }; 8159C50E2135901700197B91 /* web3swift_ERC20_Class_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8159C50D2135901700197B91 /* web3swift_ERC20_Class_Tests.swift */; }; - 8159C5102135929700197B91 /* key.json in Resources */ = {isa = PBXBuildFile; fileRef = 8159C50F2135929700197B91 /* key.json */; }; - 8159C5112135929700197B91 /* key.json in Resources */ = {isa = PBXBuildFile; fileRef = 8159C50F2135929700197B91 /* key.json */; }; 815C74C820ECBF3E00DE2AC4 /* web3swift_User_cases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 815C74C720ECBF3E00DE2AC4 /* web3swift_User_cases.swift */; }; 8160E5CE20B8245A0070070B /* IBAN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8160E5CD20B8245A0070070B /* IBAN.swift */; }; 8160E5CF20B8245A0070070B /* IBAN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8160E5CD20B8245A0070070B /* IBAN.swift */; }; @@ -150,7 +148,6 @@ 81C0FD052044A8AE00D82FAF /* Web3+Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C0FCF120440EB500D82FAF /* Web3+Protocols.swift */; }; 81C0FD062044A8D100D82FAF /* TransactionSigner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C0FCF520440F9900D82FAF /* TransactionSigner.swift */; }; 81C146F71FF274B200AA943E /* Web3+Structures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C146F61FF274B200AA943E /* Web3+Structures.swift */; }; - 81C456FE214A54D50091FF45 /* key.json in Resources */ = {isa = PBXBuildFile; fileRef = 8159C50F2135929700197B91 /* key.json */; }; 81C5DA0E207254D000424CD6 /* ABIv2Elements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C5DA0D207254D000424CD6 /* ABIv2Elements.swift */; }; 81C5DA0F207254D000424CD6 /* ABIv2Elements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C5DA0D207254D000424CD6 /* ABIv2Elements.swift */; }; 81C5DA11207254F600424CD6 /* ABIv2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C5DA10207254F600424CD6 /* ABIv2.swift */; }; @@ -205,6 +202,7 @@ 81FECD5B211AECBD006DA367 /* Web3+Eth+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81FECD5A211AECBD006DA367 /* Web3+Eth+ObjC.swift */; }; 81FECD5C211AECBD006DA367 /* Web3+Eth+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81FECD5A211AECBD006DA367 /* Web3+Eth+ObjC.swift */; }; 81FECD5E211AEFCE006DA367 /* web3swift_ObjC_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81FECD5D211AEFCE006DA367 /* web3swift_ObjC_Tests.swift */; }; + B2E668CE214F8A7B00C3CC2D /* ENS.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2E668CD214F8A7B00C3CC2D /* ENS.swift */; }; B350A445E5DB35C60E59AD70 /* libPods-web3swift-macOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 57F8C9C48884592DCF561393 /* libPods-web3swift-macOS.a */; }; E23B5ADB20EA67D800DC7F32 /* web3swift_AdvancedABIv2_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E23B5ADA20EA67D800DC7F32 /* web3swift_AdvancedABIv2_Tests.swift */; }; E23B5ADD20EA685D00DC7F32 /* web3swift_EIP67_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E23B5ADC20EA685D00DC7F32 /* web3swift_EIP67_Tests.swift */; }; @@ -287,7 +285,6 @@ 815630052008A64C00A0EC2F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 8159C50A21352CB700197B91 /* Web3+ERC20.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC20.swift"; sourceTree = ""; }; 8159C50D2135901700197B91 /* web3swift_ERC20_Class_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = web3swift_ERC20_Class_Tests.swift; sourceTree = ""; }; - 8159C50F2135929700197B91 /* key.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = key.json; sourceTree = ""; }; 815C74C720ECBF3E00DE2AC4 /* web3swift_User_cases.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = web3swift_User_cases.swift; sourceTree = ""; }; 8160E5CD20B8245A0070070B /* IBAN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IBAN.swift; sourceTree = ""; }; 817EBB0F2004FE2800E02EAA /* EthereumAddress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EthereumAddress.swift; sourceTree = ""; }; @@ -369,6 +366,7 @@ 8675751D91DB2DBC9E7A3469 /* libPods-web3swift-macOS_Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-web3swift-macOS_Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A5E8AF69880F5141B4AC9DF0 /* libPods-web3swift-iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-web3swift-iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A9ADDE40292A17C21B8D5516 /* Pods-web3swift-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-web3swift-iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-web3swift-iOS/Pods-web3swift-iOS.release.xcconfig"; sourceTree = ""; }; + B2E668CD214F8A7B00C3CC2D /* ENS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ENS.swift; sourceTree = ""; }; B48CA58D134401D3C4E8CCC5 /* Pods_Web3Swift_osx.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Web3Swift_osx.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B5AFAFC5440E52BE57C7BA13 /* Pods_web3swiftTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_web3swiftTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CA3F7E825AEBF3455D00150A /* Pods-web3swift-macOS_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-web3swift-macOS_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-web3swift-macOS_Tests/Pods-web3swift-macOS_Tests.debug.xcconfig"; sourceTree = ""; }; @@ -491,7 +489,6 @@ children = ( 81A7B2892143DF1D004CD2C7 /* web3swift_EIP681_Tests.swift */, 81A7B2782143C978004CD2C7 /* web3swift_ENS_Tests.swift */, - 8159C50F2135929700197B91 /* key.json */, 8159C50D2135901700197B91 /* web3swift_ERC20_Class_Tests.swift */, 8102F5C2211E00820032DF60 /* scrypt_Tests.swift */, 81FECD5D211AEFCE006DA367 /* web3swift_ObjC_Tests.swift */, @@ -559,6 +556,7 @@ 81FB21F8207BA78B007F9A83 /* EIP67Code.swift */, 81A7B2502143C3A8004CD2C7 /* NameHash.swift */, 81A7B2862143DBF6004CD2C7 /* EIP681.swift */, + B2E668CD214F8A7B00C3CC2D /* ENS.swift */, ); path = Classes; sourceTree = ""; @@ -1002,7 +1000,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8159C5102135929700197B91 /* key.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1010,7 +1007,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 81C456FE214A54D50091FF45 /* key.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1018,7 +1014,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8159C5112135929700197B91 /* key.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1159,6 +1154,7 @@ 810B0F9C1FEC520500CF0DA2 /* Web3+Methods.swift in Sources */, 81A1822520D678590016741F /* Promise+Web3+Eth+GetGasPrice.swift in Sources */, 8113DE7C1FD8514400CD8DF1 /* NSRegularExpressionExtension.swift in Sources */, + B2E668CE214F8A7B00C3CC2D /* ENS.swift in Sources */, 81C5DA2E2074EBF500424CD6 /* ContractABIv2.swift in Sources */, 810B0F9E1FEC5B9C00CF0DA2 /* Web3+Eth.swift in Sources */, 818D810E1FDC1A2000663CE3 /* RLP.swift in Sources */, @@ -1480,10 +1476,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; CLANG_ENABLE_MODULES = NO; - CODE_SIGN_IDENTITY = ""; + CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = U8FZ3UYF69; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -1522,7 +1518,7 @@ CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = U8FZ3UYF69; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -1559,7 +1555,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 62V9CKQN89; + DEVELOPMENT_TEAM = U8FZ3UYF69; HEADER_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = web3swiftTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -1582,7 +1578,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 62V9CKQN89; + DEVELOPMENT_TEAM = U8FZ3UYF69; HEADER_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = web3swiftTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; diff --git a/web3swift/Utils/Classes/EIP681.swift b/web3swift/Utils/Classes/EIP681.swift index d50a33028..00364be00 100644 --- a/web3swift/Utils/Classes/EIP681.swift +++ b/web3swift/Utils/Classes/EIP681.swift @@ -78,7 +78,7 @@ extension Web3 { public struct EIP681CodeParser { // static var addressRegex = "^(pay-)?([0-9a-zA-Z]+)(@[0-9]+)?" - static var addressRegex = "^(pay-)?([0-9a-zA-Z]+)(@[0-9]+)?\\/?(.*)?$" + static var addressRegex = "^(pay-)?([0-9a-zA-Z.]+)(@[0-9]+)?\\/?(.*)?$" public static func parse(_ data: Data) -> EIP681Code? { guard let string = String(data: data, encoding: .utf8) else {return nil} @@ -142,8 +142,22 @@ extension Web3 { case .ethereumAddress(let ethereumAddress): nativeValue = ethereumAddress as AnyObject case .ensAddress(let ens): - //TODO: - convert ens into ethereum - nativeValue = ens as AnyObject + let web = web3(provider: InfuraProvider(Networks.fromInt(Int(code.chainID ?? 1)) ?? Networks.Mainnet)!) + var ensModel = ENS(web3: web) + let resolver = ensModel.resolver(forDomain: ens) + switch resolver { + case .failure(_): + nativeValue = ens as AnyObject + case .success(var res): + let address = res.addr(forDomain: ens) + switch address { + case .failure(_): + nativeValue = ens as AnyObject + case .success(let res): + nativeValue = res as AnyObject + } + } + } case .uint(bits: _): if let val = BigUInt(value, radix: 10) { @@ -194,8 +208,26 @@ extension Web3 { switch comp.name { case "value": guard let value = comp.value else {return nil} - guard let val = BigUInt(value, radix: 10) else {return nil} - code.amount = val + let splittedValue = value.split(separator: "e") + if splittedValue.count <= 1 { + guard let val = BigUInt(value, radix: 10) else {return nil } + code.amount = val + } else if splittedValue.count == 2 { + guard let power = Double(splittedValue[1]) else { return nil } + let splittedNumber = String(splittedValue[0]).replacingOccurrences(of: ",", with: ".").split(separator: ".") + var a = BigUInt(pow(10, power)) + if splittedNumber.count == 1 { + guard let number = BigUInt(splittedNumber[0], radix: 10) else { return nil } + code.amount = number * a + } else if splittedNumber.count == 2 { + let stringNumber = String(splittedNumber[0]) + String(splittedNumber[1]) + let am = BigUInt(pow(10, Double(splittedNumber[1].count))) + a = a / am + guard let number = BigUInt(stringNumber, radix: 10) else { return nil } + code.amount = number * a + } else { return nil } + } else { return nil } + case "gas": guard let value = comp.value else {return nil} guard let val = BigUInt(value, radix: 10) else {return nil} diff --git a/web3swift/Utils/Classes/ENS.swift b/web3swift/Utils/Classes/ENS.swift new file mode 100644 index 000000000..1f02f62c5 --- /dev/null +++ b/web3swift/Utils/Classes/ENS.swift @@ -0,0 +1,155 @@ +// +// ENS.swift +// web3swift-iOS +// + +import Foundation +import BigInt +import Result + +public struct ENS { + + let web3: web3 + let ensContractAddress: EthereumAddress? + + init(web3: web3) { + self.web3 = web3 + switch web3.provider.network { + case .Mainnet?: + ensContractAddress = EthereumAddress("0x314159265dd8dbb310642f98f50c066173c1259b") + case .Rinkeby?: + ensContractAddress = EthereumAddress("0xe7410170f87102df0055eb195163a03b7f2bff4a") + case .Ropsten?: + ensContractAddress = EthereumAddress("0x112234455c3a32fd11230c42e7bccd4a84e02010") + default: + ensContractAddress = nil + } + } + + private lazy var registryContract: web3.web3contract = { + let contract = self.web3.contract(Web3.Utils.ensRegistryABI, at: self.ensContractAddress, abiVersion: 2) + precondition(contract != nil) + return contract! + }() + + + //MARK: - Returns resolver for the given domain + mutating func resolver(forDomain domain: String) -> Result { + guard let nameHash = NameHash.nameHash(domain) else { return Result.failure(Web3Error.dataError) } + let options = Web3Options.defaultOptions() + guard let transaction = self.registryContract.method("resolver", parameters: [nameHash as AnyObject], options: options) else { return Result.failure(Web3Error.transactionSerializationError) } + let result = transaction.call(options: options) + switch result { + case .success(let res): + guard let resolverAddress = res["0"] as? EthereumAddress else { return Result.failure(Web3Error.dataError) } + return Result(ResolverENS(web3: self.web3, resolverAddress: resolverAddress)) + case .failure(let error): + return Result.failure(error) + } + } + + //TODO: - + /* + 1. Write a function that allows map domain to the name + */ +} + +public struct ResolverENS { + let web3: web3 + let resolverAddress: EthereumAddress + + public enum InterfaceName { + case addr + case name + case ABI + case pubkey + + func hash() -> String { + switch self { + case .ABI: + return "0x2203ab56" + case .addr: + return "0x3b3b57de" + case .name: + return "0x691f3431" + case .pubkey: + return "0xc8690233" + } + } + } + + private lazy var resolverContract: web3.web3contract = { + let contract = self.web3.contract(Web3.Utils.resolverABI, at: self.resolverAddress, abiVersion: 2) + precondition(contract != nil) + return contract! + }() + + init(web3: web3, resolverAddress: EthereumAddress) { + self.web3 = web3 + self.resolverAddress = resolverAddress + } + + mutating func supportsInterface(interfaceID: Data) -> Result { + return supportsInterface(interfaceID: interfaceID.toHexString()) + } + + //MARK: - returns true if the contract supports given interface + mutating func supportsInterface(interfaceID: String) -> Result { + let options = Web3Options.defaultOptions() + guard let transaction = self.resolverContract.method("supportsInterface", parameters: [interfaceID as AnyObject], options: options) else { return Result.failure(Web3Error.transactionSerializationError) } + let result = transaction.call(options: options) + switch result { + case .success(let res): + guard let supports = res["0"] as? Bool else { return Result.failure(Web3Error.dataError) } + return Result(supports) + case .failure(let error): + return Result.failure(error) + } + } + + //MARK: - returns address for the given domain at given resolver + mutating func addr(forDomain domain: String) -> Result { + guard let nameHash = NameHash.nameHash(domain) else { return Result.failure(Web3Error.dataError) } + let options = Web3Options.defaultOptions() + guard let transaction = self.resolverContract.method("addr", parameters: [nameHash as AnyObject], options: options) else { return Result.failure(Web3Error.dataError) } + let result = transaction.call(options: options) + switch result { + case .success(let res): + return Result(res["0"] as! EthereumAddress) + case .failure(let error): + return Result.failure(error) + } + } + + //MARK: - returns corresponding ENS to the requested node + mutating func name(node: String) -> Result { + let options = Web3Options.defaultOptions() + guard let transaction = self.resolverContract.method("name", parameters: [node.lowercased() as AnyObject], options: options) else { return Result.failure(Web3Error.transactionSerializationError)} + let result = transaction.call(options: options) + switch result { + case .success(let res): + return Result(res["0"] as! String) + case .failure(let error): + return Result.failure(error) + } + + } + + //MARK: - returns ABI in the requested encodings + mutating func ABI(node: String, contentType: BigUInt) -> Result<(BigUInt, Data), Web3Error> { + let options = Web3Options.defaultOptions() + guard let transaction = self.resolverContract.method("ABI", parameters: [node, contentType] as [AnyObject], options: options) else { return Result.failure(Web3Error.transactionSerializationError) } + let result = transaction.call(options: options) + switch result { + case .success(let res): + guard let encoding = res["0"] as? BigUInt else { return Result.failure(Web3Error.dataError) } + guard let data = res["1"] as? Data else { return Result.failure(Web3Error.dataError) } + return Result((encoding, data)) + case .failure(let error): + return Result.failure(error) + } + } + + //TODO: - func pubkey() +} + diff --git a/web3swift/Web3/Classes/Web3+Utils.swift b/web3swift/Web3/Classes/Web3+Utils.swift index 3e225a58b..79e448e74 100755 --- a/web3swift/Web3/Classes/Web3+Utils.swift +++ b/web3swift/Web3/Classes/Web3+Utils.swift @@ -72,6 +72,13 @@ extension Web3.Utils { public static var erc20ABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"_initialAmount\",\"type\":\"uint256\"},{\"name\":\"_tokenName\",\"type\":\"string\"},{\"name\":\"_decimalUnits\",\"type\":\"uint8\"},{\"name\":\"_tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"payable\":false,\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},]" public static var erc721ABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_approved\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"tokenByIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"_symbol\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_operator\",\"type\":\"address\"},{\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_approved\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_operator\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"}]" + public static var ensRegistryABI = """ +[{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"label","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setSubnodeOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"ttl","type":"uint64"}],"name":"setTTL","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"ttl","outputs":[{"name":"","type":"uint64"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"resolver","type":"address"}],"name":"setResolver","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":true,"name":"label","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"resolver","type":"address"}],"name":"NewResolver","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"ttl","type":"uint64"}],"name":"NewTTL","type":"event"}] +""" + + public static var resolverABI = """ +[{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"addr","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"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":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"},{"name":"contentType","type": "uint256"}],"name":"ABI","outputs":[{"name":"","type":"uint256"},{"name":"","type":"bytes"}],"payable":false,"type":"function"}] +""" } diff --git a/web3swiftTests/web3swift_EIP681_Tests.swift b/web3swiftTests/web3swift_EIP681_Tests.swift index 2b0c9ad6e..01412bdba 100644 --- a/web3swiftTests/web3swift_EIP681_Tests.swift +++ b/web3swiftTests/web3swift_EIP681_Tests.swift @@ -19,7 +19,7 @@ class web3swift_EIP681_Tests: XCTestCase { //ethereum:0x45245bc59219eeaaf6cd3f382e078a461ff9de7b/transfer?address=0x6891dC3962e710f0ff711B9c6acc26133Fd35Cb4&uint256=1 func testEIP681Parsing() { - let parsed = Web3.EIP681CodeParser.parse("ethereum:0xfb6916095ca1df60bb79Ce92ce3ea74c37c5d359?value=2.014e18") + let parsed = Web3.EIP681CodeParser.parse("ethereum:0x5ffc014343cd971b7eb70732021e26c35b744cc4?value=2.014e18") XCTAssert(parsed != nil) } @@ -28,4 +28,9 @@ class web3swift_EIP681_Tests: XCTestCase { XCTAssert(parsed != nil) } + func testEIP681ENSParsing() { + let parsed = Web3.EIP681CodeParser.parse("ethereum:somename.eth/transfer?address=somename.eth&uint256=1") + XCTAssert(parsed != nil) + } + } diff --git a/web3swiftTests/web3swift_ENS_Tests.swift b/web3swiftTests/web3swift_ENS_Tests.swift index db24f6336..804400f75 100644 --- a/web3swiftTests/web3swift_ENS_Tests.swift +++ b/web3swiftTests/web3swift_ENS_Tests.swift @@ -21,4 +21,55 @@ class web3swift_ENS_Tests: XCTestCase { XCTAssertEqual(NameHash.nameHash("foo.eth"), Data.fromHex("0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f")) } + func testResolverAddress() { + let web = web3(provider: InfuraProvider(Networks.Mainnet)!) + var ens = ENS(web3: web) + guard case .success(let resolver) = ens.resolver(forDomain: "somename.eth") else { XCTAssert(false); return } + XCTAssertEqual(resolver.resolverAddress.address.lowercased(), "0x5ffc014343cd971b7eb70732021e26c35b744cc4") + } + + func testResolver() { + let web = web3(provider: InfuraProvider(Networks.Mainnet)!) + var ens = ENS(web3: web) + let domain = "somename.eth" + guard case .success(var resolver) = ens.resolver(forDomain: domain) else { XCTAssert(false); return } + guard case .success(let address) = resolver.addr(forDomain: domain) else { XCTAssert(false); return } + XCTAssertEqual(address.address.lowercased(), "0x3487acfb1479ad1df6c0eb56ae743d34897798ac") + + } + + func testSupportsInterface() { + let web = web3(provider: InfuraProvider(Networks.Mainnet)!) + var ens = ENS(web3: web) + let domain = "somename.eth" + guard case .success(var resolver) = ens.resolver(forDomain: domain) else { XCTAssert(false); return } + guard case .success(let isAddrSupports) = resolver.supportsInterface(interfaceID: ResolverENS.InterfaceName.addr.hash()) else { XCTAssert(false); return } + XCTAssertEqual(isAddrSupports, true) + guard case .success(let isNameSupports) = resolver.supportsInterface(interfaceID: ResolverENS.InterfaceName.name.hash()) else { XCTAssert(false); return } + XCTAssertEqual(isNameSupports, true) + guard case .success(let isABIsupports) = resolver.supportsInterface(interfaceID: ResolverENS.InterfaceName.ABI.hash()) else { XCTAssert(false); return } + XCTAssertEqual(isABIsupports, true) + guard case .success(let isPubkeySupports) = resolver.supportsInterface(interfaceID: ResolverENS.InterfaceName.pubkey.hash()) else { XCTAssert(false); return } + XCTAssertEqual(isPubkeySupports, true) + } + + func testABI() { + let web = web3(provider: InfuraProvider(Networks.Mainnet)!) + var ens = ENS(web3: web) + let domain = "somename.eth" + guard case .success(var resolver) = ens.resolver(forDomain: domain) else { XCTAssert(false); return } + guard case .success(let isABIsupported) = resolver.supportsInterface(interfaceID: ResolverENS.InterfaceName.ABI.hash()) else { XCTAssert(false); return } + if isABIsupported { + guard case .success(let res) = resolver.ABI(node: domain, contentType: 2) else { XCTAssert(false); return } + XCTAssert(res.0 == 0) + XCTAssert(res.1.count == 0) + } + } + + func testName() { + //TODO + } + + + }