Skip to content

Commit cfd3f90

Browse files
author
Alex Vlasov
committed
EthereumAddress now has fail-able initializer
Bridging synchronous API to asynchronous API to eliminate doing the same work
1 parent 127acb2 commit cfd3f90

20 files changed

+649
-342
lines changed

Example/web3swiftExample/web3swiftExample/ViewController.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,19 @@ class ViewController: UIViewController {
117117
print(err)
118118
}
119119

120-
120+
//Send ERC20 token on Rinkeby
121121
guard case .success(let gasPriceRinkeby) = web3Rinkeby.eth.getGasPrice() else {return}
122122
web3Rinkeby.addKeystoreManager(keystoreManager)
123123
var tokenTransferOptions = Web3Options.defaultOptions()
124124
tokenTransferOptions.gasPrice = gasPriceRinkeby
125125
tokenTransferOptions.from = ks?.addresses?.first!
126126
let testToken = web3Rinkeby.contract(Web3.Utils.erc20ABI, at: EthereumAddress("0xa407dd0cbc9f9d20cdbd557686625e586c85b20a"), abiVersion: 2)!
127127
let intermediateForTokenTransfer = testToken.method("transfer", parameters: [EthereumAddress("0x6394b37Cf80A7358b38068f0CA4760ad49983a1B"), BigUInt(1)] as [AnyObject], options: tokenTransferOptions)!
128-
let tokenTransferResult = intermediateForTokenTransfer.send(password: "BANKEXFOUNDATION")
128+
let gasEstimateResult = intermediateForTokenTransfer.estimateGas(options: nil)
129+
guard case .success(let gasEstimate) = gasEstimateResult else {return}
130+
var optionsWithCustomGasLimit = Web3Options()
131+
optionsWithCustomGasLimit.gasLimit = gasEstimate
132+
let tokenTransferResult = intermediateForTokenTransfer.send(password: "BANKEXFOUNDATION", options: optionsWithCustomGasLimit)
129133
switch tokenTransferResult {
130134
case .success(let res):
131135
print("Token transfer successful")

web3swift/ABI/Classes/ABIEncoder.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ extension ABIElement.ParameterType.StaticType {
4848
}
4949
case .address:
5050
if let string = value as? String {
51-
let address = EthereumAddress(string)
52-
guard address.isValid else {return nil}
51+
guard let address = EthereumAddress(string) else {return nil}
5352
let data = address.addressData
5453
return data.setLengthLeft(32)
5554
} else if let address = value as? EthereumAddress {

web3swift/ABIv2/Classes/ABIv2Encoding.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,7 @@ extension ABIv2Encoder {
200200
}
201201
case .address:
202202
if let string = value as? String {
203-
let address = EthereumAddress(string)
204-
guard address.isValid else {break}
203+
guard let address = EthereumAddress(string) else {return nil}
205204
let data = address.addressData
206205
return data.setLengthLeft(32)
207206
} else if let address = value as? EthereumAddress {

web3swift/Concurrency/Classes/Web3+ConversionOperations.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,9 @@ final class AddressArrayConversionOperation: Web3Operation {
153153
}
154154
var toReturn = [EthereumAddress]()
155155
for addrString in resultArray {
156-
let addr = EthereumAddress(addrString)
156+
guard let addr = EthereumAddress(addrString) else {
157+
return processError(Web3Error.dataError)
158+
}
157159
if (addr.isValid) {
158160
toReturn.append(addr)
159161
}

web3swift/Concurrency/Classes/Web3+EthOperations.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ final class GetTransactionCountOperation: Web3Operation {
5656
guard input.count == 2 else {return processError(Web3Error.inputError("Invalid input supplied"))}
5757
guard let address = input[0] as? String else {return processError(Web3Error.inputError("Invalid input supplied"))}
5858
guard let onBlock = input[1] as? String else {return processError(Web3Error.inputError("Invalid input supplied"))}
59-
guard EthereumAddress(address).isValid else {return processError(Web3Error.inputError("Invalid input supplied"))}
59+
guard let _ = EthereumAddress(address) else {return processError(Web3Error.inputError("Invalid input supplied"))}
6060
let request = JSONRPCRequestFabric.prepareRequest(.getTransactionCount, parameters: [address, onBlock])
6161
let dataOp = DataFetchOperation(self.web3, queue: self.expectedQueue)
6262
dataOp.inputData = request as AnyObject
@@ -87,7 +87,7 @@ final class GetBalanceOperation: Web3Operation {
8787
guard input.count == 2 else {return processError(Web3Error.inputError("Invalid input supplied"))}
8888
guard let address = input[0] as? String else {return processError(Web3Error.inputError("Invalid input supplied"))}
8989
guard let onBlock = input[1] as? String else {return processError(Web3Error.inputError("Invalid input supplied"))}
90-
guard EthereumAddress(address).isValid else {return processError(Web3Error.inputError("Invalid input supplied"))}
90+
guard let _ = EthereumAddress(address) else {return processError(Web3Error.inputError("Invalid input supplied"))}
9191
let request = JSONRPCRequestFabric.prepareRequest(.getBalance, parameters: [address, onBlock])
9292
let dataOp = DataFetchOperation(self.web3, queue: self.expectedQueue)
9393
dataOp.inputData = request as AnyObject
@@ -150,7 +150,8 @@ final class EstimateGasOperation: Web3Operation {
150150
guard let transaction = input[0] as? EthereumTransaction else {return processError(Web3Error.inputError("Invalid input supplied"))}
151151
let options = input[1] as? Web3Options
152152
guard let onBlock = input[2] as? String else {return processError(Web3Error.inputError("Invalid input supplied"))}
153-
let mergedOptions = Web3Options.merge(Web3Options.defaultOptions(), with: options)
153+
var mergedOptions = Web3Options.merge(Web3Options.defaultOptions(), with: options)
154+
mergedOptions?.gasLimit = nil
154155
guard let request = EthereumTransaction.createRequest(method: JSONRPCmethod.estimateGas, transaction: transaction, onBlock: onBlock, options: mergedOptions) else {return processError(Web3Error.inputError("Invalid input supplied"))}
155156
let dataOp = DataFetchOperation(self.web3, queue: self.expectedQueue)
156157
dataOp.inputData = request as AnyObject

web3swift/Concurrency/Classes/Web3+NativePrimitivesConversionOperations.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,25 @@ final class TransactionReceiptConversionOperation: Web3Operation {
2929
}
3030
}
3131

32+
final class TransactionDetailsConversionOperation: Web3Operation {
33+
34+
override func main() {
35+
if (error != nil) {
36+
return self.processError(self.error!)
37+
}
38+
guard let _ = self.next else {return processError(Web3Error.inputError("Invalid input supplied"))}
39+
if inputData == nil || inputData! is NSNull {
40+
return processSuccess(TransactionReceipt.notProcessed(transactionHash: Data()) as AnyObject)
41+
}
42+
guard inputData != nil else {return processError(Web3Error.inputError("Invalid input supplied"))}
43+
guard let input = inputData! as? [String: AnyObject] else {return processError(Web3Error.dataError)}
44+
guard let receipt = TransactionDetails(input) else {
45+
return processError(Web3Error.dataError)
46+
}
47+
return processSuccess(receipt as AnyObject)
48+
}
49+
}
50+
3251
final class BlockConversionOperation: Web3Operation {
3352

3453
override func main() {

web3swift/Concurrency/Classes/Web3+PersonalOperations.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ final class PersonalUnlockAccountOperation: Web3Operation {
3030
guard let address = input[0] as? String else {return processError(Web3Error.inputError("Invalid input supplied"))}
3131
guard let password = input[1] as? String else {return processError(Web3Error.inputError("Invalid input supplied"))}
3232
guard let seconds = input[2] as? UInt64 else {return processError(Web3Error.inputError("Invalid input supplied"))}
33-
guard EthereumAddress(address).isValid else {return processError(Web3Error.inputError("Invalid input supplied"))}
33+
guard let _ = EthereumAddress(address) else {return processError(Web3Error.inputError("Invalid input supplied"))}
3434
let request = JSONRPCRequestFabric.prepareRequest(.unlockAccount, parameters: [address, password, seconds])
3535
let dataOp = DataFetchOperation(self.web3, queue: self.expectedQueue)
3636
dataOp.inputData = request as AnyObject

web3swift/Concurrency/Classes/Web3+TransactionAndBlockDetailsOperations.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ final class GetTransactionDetailsOperation: Web3Operation {
3131
dataOp.inputData = request as AnyObject
3232
let convOp = DictionaryConversionOperation(self.web3, queue: self.expectedQueue)
3333
dataOp.next = OperationChainingType.operation(convOp)
34-
let parsingOp = TransactionReceiptConversionOperation(self.web3, queue: self.expectedQueue)
34+
let parsingOp = TransactionDetailsConversionOperation(self.web3, queue: self.expectedQueue)
3535
convOp.next = OperationChainingType.operation(parsingOp)
3636
parsingOp.next = completion
3737
self.expectedQueue.addOperation(dataOp)

web3swift/Concurrency/Classes/Web3+TransactionOperations.swift

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,11 @@ final class ContractSendOperation: Web3Operation {
106106

107107
convenience init?(_ web3Instance: web3, queue: OperationQueue? = nil, contract: web3.web3contract, method: String = "fallback", parameters: [AnyObject] = [], extraData: Data = Data(), options: Web3Options?, onBlock: String = "pending", password: String = "BANKEXFOUNDATION") {
108108
guard let intermediate = contract.method(method, parameters: parameters, extraData: extraData, options: options) else {return nil}
109-
self.init(web3Instance, queue: queue, inputData: [intermediate, password, onBlock] as AnyObject)
109+
self.init(web3Instance, queue: queue, inputData: [intermediate, password, onBlock, options] as AnyObject)
110110
}
111111

112-
convenience init?(_ web3Instance: web3, queue: OperationQueue? = nil, intermediate: TransactionIntermediate, onBlock: String = "pending", password: String = "BANKEXFOUNDATION") {
113-
self.init(web3Instance, queue: queue, inputData: [intermediate, password, onBlock] as AnyObject)
112+
convenience init?(_ web3Instance: web3, queue: OperationQueue? = nil, intermediate: TransactionIntermediate, options: Web3Options? = nil, onBlock: String = "pending", password: String = "BANKEXFOUNDATION") {
113+
self.init(web3Instance, queue: queue, inputData: [intermediate, password, onBlock, options] as AnyObject)
114114
}
115115

116116
override func main() {
@@ -124,30 +124,30 @@ final class ContractSendOperation: Web3Operation {
124124
guard let intermediate = input[0] as? TransactionIntermediate else {return processError(Web3Error.inputError("Invalid input supplied"))}
125125
guard let password = input[1] as? String else {return processError(Web3Error.inputError("Invalid input supplied"))}
126126
guard let onBlock = input[2] as? String else {return processError(Web3Error.inputError("Invalid input supplied"))}
127-
128-
guard let from = intermediate.options?.from else {return processError(Web3Error.inputError("Invalid input supplied"))}
127+
let options = input[3] as? Web3Options
128+
guard var mergedOptions = Web3Options.merge(intermediate.options, with: options) else {return processError(Web3Error.inputError("Invalid input supplied"))}
129+
guard let from = mergedOptions.from else {return processError(Web3Error.inputError("Invalid input supplied"))}
129130
var transaction = intermediate.transaction
130-
guard var options = intermediate.options else {return self.processError(Web3Error.dataError)}
131131

132132
let gasEstimationCallback = { (res: Result<AnyObject, Web3Error>) -> () in
133133
switch res {
134134
case .success(let result):
135135
guard let gasEstimate = result as? BigUInt else {
136136
return self.processError(Web3Error.dataError)
137137
}
138-
if options.gasLimit == nil {
139-
options.gasLimit = gasEstimate
138+
if mergedOptions.gasLimit == nil {
139+
mergedOptions.gasLimit = gasEstimate
140140
} else {
141-
if (options.gasLimit! < gasEstimate) {
142-
return self.processError(Web3Error.inputError("Estimated gas is larger than the gas limit"))
141+
if (mergedOptions.gasLimit! < gasEstimate) {
142+
if (options?.gasLimit != nil && options!.gasLimit != nil && options!.gasLimit! >= gasEstimate) {
143+
mergedOptions.gasLimit = gasEstimate
144+
} else {
145+
return self.processError(Web3Error.inputError("Estimated gas is larger than the gas limit"))
146+
}
143147
}
144-
options.gasLimit = gasEstimate
145-
}
146-
if options.gasLimit != nil {
147-
transaction.gasLimit = options.gasLimit!
148148
}
149149
intermediate.transaction = transaction
150-
intermediate.options = options
150+
intermediate.options = mergedOptions
151151
let sendOp = SendTransactionOperation.init(self.web3, queue: self.expectedQueue, transactionIntermediate: intermediate, password: password)
152152
sendOp.next = completion
153153
self.expectedQueue.addOperation(sendOp)
@@ -168,7 +168,6 @@ final class ContractSendOperation: Web3Operation {
168168
}
169169
transaction.nonce = nonce
170170
intermediate.transaction = transaction
171-
intermediate.options = options
172171
guard let gasEstimateOperation = ContractEstimateGasOperation.init(self.web3, queue: self.expectedQueue, intermediate: intermediate, onBlock: onBlock) else {return self.processError(Web3Error.dataError)}
173172
gasEstimateOperation.next = OperationChainingType.callback(gasEstimationCallback, self.expectedQueue)
174173
self.expectedQueue.addOperation(gasEstimateOperation)
@@ -184,14 +183,11 @@ final class ContractSendOperation: Web3Operation {
184183
guard let gasPrice = result as? BigUInt else {
185184
return self.processError(Web3Error.dataError)
186185
}
187-
if options.gasPrice == nil {
188-
options.gasPrice = gasPrice
189-
}
190-
if options.gasPrice != nil {
191-
transaction.gasPrice = options.gasPrice!
186+
if mergedOptions.gasPrice == nil {
187+
mergedOptions.gasPrice = gasPrice
192188
}
193189
intermediate.transaction = transaction
194-
intermediate.options = options
190+
intermediate.options = mergedOptions
195191

196192
let nonceOp = GetTransactionCountOperation.init(self.web3, queue: self.expectedQueue, address: from, onBlock: onBlock)
197193
nonceOp.next = OperationChainingType.callback(nonceCallback, self.expectedQueue)

web3swift/HookedFunctions/Classes/Web3+BrowserFunctions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ extension web3.BrowserFunctions {
4040
do {
4141
guard let keystoreManager = self.web3.provider.attachedKeystoreManager else {return nil}
4242

43-
guard let signature = try Web3Signer.signPersonalMessage(personalMessage, keystore: keystoreManager, account: EthereumAddress(account), password: password) else {return nil}
43+
guard let signature = try Web3Signer.signPersonalMessage(personalMessage, keystore: keystoreManager, account: EthereumAddress(account)!, password: password) else {return nil}
4444
guard let sender = self.personalECRecover(personalMessage, signature: signature) else {return nil}
4545
print(sender)
4646
if sender.lowercased() != account.lowercased() {

0 commit comments

Comments
 (0)