Skip to content

Commit ae0330c

Browse files
authored
Merge pull request #38 from matterinc/feature/ENS
Basic ENS support added, EIP681 parsing supports ENS from now.
2 parents fb46ac5 + 99b076b commit ae0330c

File tree

6 files changed

+265
-19
lines changed

6 files changed

+265
-19
lines changed

web3swift.xcodeproj/project.pbxproj

+9-13
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@
8181
8159C50B21352CB700197B91 /* Web3+ERC20.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8159C50A21352CB700197B91 /* Web3+ERC20.swift */; };
8282
8159C50C21352CB700197B91 /* Web3+ERC20.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8159C50A21352CB700197B91 /* Web3+ERC20.swift */; };
8383
8159C50E2135901700197B91 /* web3swift_ERC20_Class_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8159C50D2135901700197B91 /* web3swift_ERC20_Class_Tests.swift */; };
84-
8159C5102135929700197B91 /* key.json in Resources */ = {isa = PBXBuildFile; fileRef = 8159C50F2135929700197B91 /* key.json */; };
85-
8159C5112135929700197B91 /* key.json in Resources */ = {isa = PBXBuildFile; fileRef = 8159C50F2135929700197B91 /* key.json */; };
8684
815C74C820ECBF3E00DE2AC4 /* web3swift_User_cases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 815C74C720ECBF3E00DE2AC4 /* web3swift_User_cases.swift */; };
8785
8160E5CE20B8245A0070070B /* IBAN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8160E5CD20B8245A0070070B /* IBAN.swift */; };
8886
8160E5CF20B8245A0070070B /* IBAN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8160E5CD20B8245A0070070B /* IBAN.swift */; };
@@ -150,7 +148,6 @@
150148
81C0FD052044A8AE00D82FAF /* Web3+Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C0FCF120440EB500D82FAF /* Web3+Protocols.swift */; };
151149
81C0FD062044A8D100D82FAF /* TransactionSigner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C0FCF520440F9900D82FAF /* TransactionSigner.swift */; };
152150
81C146F71FF274B200AA943E /* Web3+Structures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C146F61FF274B200AA943E /* Web3+Structures.swift */; };
153-
81C456FE214A54D50091FF45 /* key.json in Resources */ = {isa = PBXBuildFile; fileRef = 8159C50F2135929700197B91 /* key.json */; };
154151
81C5DA0E207254D000424CD6 /* ABIv2Elements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C5DA0D207254D000424CD6 /* ABIv2Elements.swift */; };
155152
81C5DA0F207254D000424CD6 /* ABIv2Elements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C5DA0D207254D000424CD6 /* ABIv2Elements.swift */; };
156153
81C5DA11207254F600424CD6 /* ABIv2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81C5DA10207254F600424CD6 /* ABIv2.swift */; };
@@ -205,6 +202,7 @@
205202
81FECD5B211AECBD006DA367 /* Web3+Eth+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81FECD5A211AECBD006DA367 /* Web3+Eth+ObjC.swift */; };
206203
81FECD5C211AECBD006DA367 /* Web3+Eth+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81FECD5A211AECBD006DA367 /* Web3+Eth+ObjC.swift */; };
207204
81FECD5E211AEFCE006DA367 /* web3swift_ObjC_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81FECD5D211AEFCE006DA367 /* web3swift_ObjC_Tests.swift */; };
205+
B2E668CE214F8A7B00C3CC2D /* ENS.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2E668CD214F8A7B00C3CC2D /* ENS.swift */; };
208206
B350A445E5DB35C60E59AD70 /* libPods-web3swift-macOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 57F8C9C48884592DCF561393 /* libPods-web3swift-macOS.a */; };
209207
E23B5ADB20EA67D800DC7F32 /* web3swift_AdvancedABIv2_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E23B5ADA20EA67D800DC7F32 /* web3swift_AdvancedABIv2_Tests.swift */; };
210208
E23B5ADD20EA685D00DC7F32 /* web3swift_EIP67_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E23B5ADC20EA685D00DC7F32 /* web3swift_EIP67_Tests.swift */; };
@@ -287,7 +285,6 @@
287285
815630052008A64C00A0EC2F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
288286
8159C50A21352CB700197B91 /* Web3+ERC20.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC20.swift"; sourceTree = "<group>"; };
289287
8159C50D2135901700197B91 /* web3swift_ERC20_Class_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = web3swift_ERC20_Class_Tests.swift; sourceTree = "<group>"; };
290-
8159C50F2135929700197B91 /* key.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = key.json; sourceTree = "<group>"; };
291288
815C74C720ECBF3E00DE2AC4 /* web3swift_User_cases.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = web3swift_User_cases.swift; sourceTree = "<group>"; };
292289
8160E5CD20B8245A0070070B /* IBAN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IBAN.swift; sourceTree = "<group>"; };
293290
817EBB0F2004FE2800E02EAA /* EthereumAddress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EthereumAddress.swift; sourceTree = "<group>"; };
@@ -369,6 +366,7 @@
369366
8675751D91DB2DBC9E7A3469 /* libPods-web3swift-macOS_Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-web3swift-macOS_Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
370367
A5E8AF69880F5141B4AC9DF0 /* libPods-web3swift-iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-web3swift-iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; };
371368
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 = "<group>"; };
369+
B2E668CD214F8A7B00C3CC2D /* ENS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ENS.swift; sourceTree = "<group>"; };
372370
B48CA58D134401D3C4E8CCC5 /* Pods_Web3Swift_osx.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Web3Swift_osx.framework; sourceTree = BUILT_PRODUCTS_DIR; };
373371
B5AFAFC5440E52BE57C7BA13 /* Pods_web3swiftTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_web3swiftTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
374372
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 = "<group>"; };
@@ -491,7 +489,6 @@
491489
children = (
492490
81A7B2892143DF1D004CD2C7 /* web3swift_EIP681_Tests.swift */,
493491
81A7B2782143C978004CD2C7 /* web3swift_ENS_Tests.swift */,
494-
8159C50F2135929700197B91 /* key.json */,
495492
8159C50D2135901700197B91 /* web3swift_ERC20_Class_Tests.swift */,
496493
8102F5C2211E00820032DF60 /* scrypt_Tests.swift */,
497494
81FECD5D211AEFCE006DA367 /* web3swift_ObjC_Tests.swift */,
@@ -559,6 +556,7 @@
559556
81FB21F8207BA78B007F9A83 /* EIP67Code.swift */,
560557
81A7B2502143C3A8004CD2C7 /* NameHash.swift */,
561558
81A7B2862143DBF6004CD2C7 /* EIP681.swift */,
559+
B2E668CD214F8A7B00C3CC2D /* ENS.swift */,
562560
);
563561
path = Classes;
564562
sourceTree = "<group>";
@@ -1002,23 +1000,20 @@
10021000
isa = PBXResourcesBuildPhase;
10031001
buildActionMask = 2147483647;
10041002
files = (
1005-
8159C5102135929700197B91 /* key.json in Resources */,
10061003
);
10071004
runOnlyForDeploymentPostprocessing = 0;
10081005
};
10091006
1CD91B2D1FD769A6007BFB45 /* Resources */ = {
10101007
isa = PBXResourcesBuildPhase;
10111008
buildActionMask = 2147483647;
10121009
files = (
1013-
81C456FE214A54D50091FF45 /* key.json in Resources */,
10141010
);
10151011
runOnlyForDeploymentPostprocessing = 0;
10161012
};
10171013
417715D220362916005C3E16 /* Resources */ = {
10181014
isa = PBXResourcesBuildPhase;
10191015
buildActionMask = 2147483647;
10201016
files = (
1021-
8159C5112135929700197B91 /* key.json in Resources */,
10221017
);
10231018
runOnlyForDeploymentPostprocessing = 0;
10241019
};
@@ -1159,6 +1154,7 @@
11591154
810B0F9C1FEC520500CF0DA2 /* Web3+Methods.swift in Sources */,
11601155
81A1822520D678590016741F /* Promise+Web3+Eth+GetGasPrice.swift in Sources */,
11611156
8113DE7C1FD8514400CD8DF1 /* NSRegularExpressionExtension.swift in Sources */,
1157+
B2E668CE214F8A7B00C3CC2D /* ENS.swift in Sources */,
11621158
81C5DA2E2074EBF500424CD6 /* ContractABIv2.swift in Sources */,
11631159
810B0F9E1FEC5B9C00CF0DA2 /* Web3+Eth.swift in Sources */,
11641160
818D810E1FDC1A2000663CE3 /* RLP.swift in Sources */,
@@ -1480,10 +1476,10 @@
14801476
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
14811477
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;
14821478
CLANG_ENABLE_MODULES = NO;
1483-
CODE_SIGN_IDENTITY = "";
1479+
CODE_SIGN_IDENTITY = "iPhone Developer";
14841480
CODE_SIGN_STYLE = Automatic;
14851481
DEFINES_MODULE = YES;
1486-
DEVELOPMENT_TEAM = "";
1482+
DEVELOPMENT_TEAM = U8FZ3UYF69;
14871483
DYLIB_COMPATIBILITY_VERSION = 1;
14881484
DYLIB_CURRENT_VERSION = 1;
14891485
DYLIB_INSTALL_NAME_BASE = "@rpath";
@@ -1522,7 +1518,7 @@
15221518
CODE_SIGN_IDENTITY = "";
15231519
CODE_SIGN_STYLE = Automatic;
15241520
DEFINES_MODULE = YES;
1525-
DEVELOPMENT_TEAM = "";
1521+
DEVELOPMENT_TEAM = U8FZ3UYF69;
15261522
DYLIB_COMPATIBILITY_VERSION = 1;
15271523
DYLIB_CURRENT_VERSION = 1;
15281524
DYLIB_INSTALL_NAME_BASE = "@rpath";
@@ -1559,7 +1555,7 @@
15591555
CODE_SIGN_IDENTITY = "iPhone Developer";
15601556
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
15611557
CODE_SIGN_STYLE = Automatic;
1562-
DEVELOPMENT_TEAM = 62V9CKQN89;
1558+
DEVELOPMENT_TEAM = U8FZ3UYF69;
15631559
HEADER_SEARCH_PATHS = "$(inherited)";
15641560
INFOPLIST_FILE = web3swiftTests/Info.plist;
15651561
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -1582,7 +1578,7 @@
15821578
CODE_SIGN_IDENTITY = "iPhone Developer";
15831579
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
15841580
CODE_SIGN_STYLE = Automatic;
1585-
DEVELOPMENT_TEAM = 62V9CKQN89;
1581+
DEVELOPMENT_TEAM = U8FZ3UYF69;
15861582
HEADER_SEARCH_PATHS = "$(inherited)";
15871583
INFOPLIST_FILE = web3swiftTests/Info.plist;
15881584
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";

web3swift/Utils/Classes/EIP681.swift

+37-5
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ extension Web3 {
7878

7979
public struct EIP681CodeParser {
8080
// static var addressRegex = "^(pay-)?([0-9a-zA-Z]+)(@[0-9]+)?"
81-
static var addressRegex = "^(pay-)?([0-9a-zA-Z]+)(@[0-9]+)?\\/?(.*)?$"
81+
static var addressRegex = "^(pay-)?([0-9a-zA-Z.]+)(@[0-9]+)?\\/?(.*)?$"
8282

8383
public static func parse(_ data: Data) -> EIP681Code? {
8484
guard let string = String(data: data, encoding: .utf8) else {return nil}
@@ -142,8 +142,22 @@ extension Web3 {
142142
case .ethereumAddress(let ethereumAddress):
143143
nativeValue = ethereumAddress as AnyObject
144144
case .ensAddress(let ens):
145-
//TODO: - convert ens into ethereum
146-
nativeValue = ens as AnyObject
145+
let web = web3(provider: InfuraProvider(Networks.fromInt(Int(code.chainID ?? 1)) ?? Networks.Mainnet)!)
146+
var ensModel = ENS(web3: web)
147+
let resolver = ensModel.resolver(forDomain: ens)
148+
switch resolver {
149+
case .failure(_):
150+
nativeValue = ens as AnyObject
151+
case .success(var res):
152+
let address = res.addr(forDomain: ens)
153+
switch address {
154+
case .failure(_):
155+
nativeValue = ens as AnyObject
156+
case .success(let res):
157+
nativeValue = res as AnyObject
158+
}
159+
}
160+
147161
}
148162
case .uint(bits: _):
149163
if let val = BigUInt(value, radix: 10) {
@@ -194,8 +208,26 @@ extension Web3 {
194208
switch comp.name {
195209
case "value":
196210
guard let value = comp.value else {return nil}
197-
guard let val = BigUInt(value, radix: 10) else {return nil}
198-
code.amount = val
211+
let splittedValue = value.split(separator: "e")
212+
if splittedValue.count <= 1 {
213+
guard let val = BigUInt(value, radix: 10) else {return nil }
214+
code.amount = val
215+
} else if splittedValue.count == 2 {
216+
guard let power = Double(splittedValue[1]) else { return nil }
217+
let splittedNumber = String(splittedValue[0]).replacingOccurrences(of: ",", with: ".").split(separator: ".")
218+
var a = BigUInt(pow(10, power))
219+
if splittedNumber.count == 1 {
220+
guard let number = BigUInt(splittedNumber[0], radix: 10) else { return nil }
221+
code.amount = number * a
222+
} else if splittedNumber.count == 2 {
223+
let stringNumber = String(splittedNumber[0]) + String(splittedNumber[1])
224+
let am = BigUInt(pow(10, Double(splittedNumber[1].count)))
225+
a = a / am
226+
guard let number = BigUInt(stringNumber, radix: 10) else { return nil }
227+
code.amount = number * a
228+
} else { return nil }
229+
} else { return nil }
230+
199231
case "gas":
200232
guard let value = comp.value else {return nil}
201233
guard let val = BigUInt(value, radix: 10) else {return nil}

web3swift/Utils/Classes/ENS.swift

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
//
2+
// ENS.swift
3+
// web3swift-iOS
4+
//
5+
6+
import Foundation
7+
import BigInt
8+
import Result
9+
10+
public struct ENS {
11+
12+
let web3: web3
13+
let ensContractAddress: EthereumAddress?
14+
15+
init(web3: web3) {
16+
self.web3 = web3
17+
switch web3.provider.network {
18+
case .Mainnet?:
19+
ensContractAddress = EthereumAddress("0x314159265dd8dbb310642f98f50c066173c1259b")
20+
case .Rinkeby?:
21+
ensContractAddress = EthereumAddress("0xe7410170f87102df0055eb195163a03b7f2bff4a")
22+
case .Ropsten?:
23+
ensContractAddress = EthereumAddress("0x112234455c3a32fd11230c42e7bccd4a84e02010")
24+
default:
25+
ensContractAddress = nil
26+
}
27+
}
28+
29+
private lazy var registryContract: web3.web3contract = {
30+
let contract = self.web3.contract(Web3.Utils.ensRegistryABI, at: self.ensContractAddress, abiVersion: 2)
31+
precondition(contract != nil)
32+
return contract!
33+
}()
34+
35+
36+
//MARK: - Returns resolver for the given domain
37+
mutating func resolver(forDomain domain: String) -> Result<ResolverENS, Web3Error> {
38+
guard let nameHash = NameHash.nameHash(domain) else { return Result.failure(Web3Error.dataError) }
39+
let options = Web3Options.defaultOptions()
40+
guard let transaction = self.registryContract.method("resolver", parameters: [nameHash as AnyObject], options: options) else { return Result.failure(Web3Error.transactionSerializationError) }
41+
let result = transaction.call(options: options)
42+
switch result {
43+
case .success(let res):
44+
guard let resolverAddress = res["0"] as? EthereumAddress else { return Result.failure(Web3Error.dataError) }
45+
return Result(ResolverENS(web3: self.web3, resolverAddress: resolverAddress))
46+
case .failure(let error):
47+
return Result.failure(error)
48+
}
49+
}
50+
51+
//TODO: -
52+
/*
53+
1. Write a function that allows map domain to the name
54+
*/
55+
}
56+
57+
public struct ResolverENS {
58+
let web3: web3
59+
let resolverAddress: EthereumAddress
60+
61+
public enum InterfaceName {
62+
case addr
63+
case name
64+
case ABI
65+
case pubkey
66+
67+
func hash() -> String {
68+
switch self {
69+
case .ABI:
70+
return "0x2203ab56"
71+
case .addr:
72+
return "0x3b3b57de"
73+
case .name:
74+
return "0x691f3431"
75+
case .pubkey:
76+
return "0xc8690233"
77+
}
78+
}
79+
}
80+
81+
private lazy var resolverContract: web3.web3contract = {
82+
let contract = self.web3.contract(Web3.Utils.resolverABI, at: self.resolverAddress, abiVersion: 2)
83+
precondition(contract != nil)
84+
return contract!
85+
}()
86+
87+
init(web3: web3, resolverAddress: EthereumAddress) {
88+
self.web3 = web3
89+
self.resolverAddress = resolverAddress
90+
}
91+
92+
mutating func supportsInterface(interfaceID: Data) -> Result<Bool, Web3Error> {
93+
return supportsInterface(interfaceID: interfaceID.toHexString())
94+
}
95+
96+
//MARK: - returns true if the contract supports given interface
97+
mutating func supportsInterface(interfaceID: String) -> Result<Bool, Web3Error> {
98+
let options = Web3Options.defaultOptions()
99+
guard let transaction = self.resolverContract.method("supportsInterface", parameters: [interfaceID as AnyObject], options: options) else { return Result.failure(Web3Error.transactionSerializationError) }
100+
let result = transaction.call(options: options)
101+
switch result {
102+
case .success(let res):
103+
guard let supports = res["0"] as? Bool else { return Result.failure(Web3Error.dataError) }
104+
return Result(supports)
105+
case .failure(let error):
106+
return Result.failure(error)
107+
}
108+
}
109+
110+
//MARK: - returns address for the given domain at given resolver
111+
mutating func addr(forDomain domain: String) -> Result<EthereumAddress, Web3Error> {
112+
guard let nameHash = NameHash.nameHash(domain) else { return Result.failure(Web3Error.dataError) }
113+
let options = Web3Options.defaultOptions()
114+
guard let transaction = self.resolverContract.method("addr", parameters: [nameHash as AnyObject], options: options) else { return Result.failure(Web3Error.dataError) }
115+
let result = transaction.call(options: options)
116+
switch result {
117+
case .success(let res):
118+
return Result(res["0"] as! EthereumAddress)
119+
case .failure(let error):
120+
return Result.failure(error)
121+
}
122+
}
123+
124+
//MARK: - returns corresponding ENS to the requested node
125+
mutating func name(node: String) -> Result<String, Web3Error> {
126+
let options = Web3Options.defaultOptions()
127+
guard let transaction = self.resolverContract.method("name", parameters: [node.lowercased() as AnyObject], options: options) else { return Result.failure(Web3Error.transactionSerializationError)}
128+
let result = transaction.call(options: options)
129+
switch result {
130+
case .success(let res):
131+
return Result(res["0"] as! String)
132+
case .failure(let error):
133+
return Result.failure(error)
134+
}
135+
136+
}
137+
138+
//MARK: - returns ABI in the requested encodings
139+
mutating func ABI(node: String, contentType: BigUInt) -> Result<(BigUInt, Data), Web3Error> {
140+
let options = Web3Options.defaultOptions()
141+
guard let transaction = self.resolverContract.method("ABI", parameters: [node, contentType] as [AnyObject], options: options) else { return Result.failure(Web3Error.transactionSerializationError) }
142+
let result = transaction.call(options: options)
143+
switch result {
144+
case .success(let res):
145+
guard let encoding = res["0"] as? BigUInt else { return Result.failure(Web3Error.dataError) }
146+
guard let data = res["1"] as? Data else { return Result.failure(Web3Error.dataError) }
147+
return Result((encoding, data))
148+
case .failure(let error):
149+
return Result.failure(error)
150+
}
151+
}
152+
153+
//TODO: - func pubkey()
154+
}
155+

0 commit comments

Comments
 (0)