Skip to content

Commit

Permalink
tested read, send and gas estimations. Enough functions to send ETH a…
Browse files Browse the repository at this point in the history
…nd ERC20 tokens
  • Loading branch information
Alex Vlasov committed Dec 20, 2017
1 parent 4dd3016 commit 0980217
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 43 deletions.
41 changes: 31 additions & 10 deletions web3Swift-Demo/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class ViewController: UIViewController {
guard let web3 = Web3.newWeb3() else {return}
let contract = web3.contract(jsonString, at: constractAddress)
let intermediate = contract?.method("name", parameters:parameters, options: options)
let result = try await((intermediate?.call(options: options))!)
let result = try await((intermediate?.call(options: options, network: .Mainnet))!)
print(result)
let userDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let keystoreManager = try KeystoreManagerV3(userDir + "/keystore")
Expand All @@ -56,31 +56,52 @@ class ViewController: UIViewController {
ks = keystoreManager?.wallets[(keystoreManager?.knownAddresses[0])!]
}
guard let sender = ks?.address else {return}
// let coldWalletABI = "[{\"payable\":true,\"type\":\"fallback\"}]"
// let coldWalletAddress = EthereumAddress("0x6394b37Cf80A7358b38068f0CA4760ad49983a1B")
// let coldWalletContract = web3.contract(coldWalletABI, at: coldWalletAddress)
// options = Web3Options.defaultOptions()
// options.gas = BigUInt(21000)
// options.from = ks?.address!
// options.value = BigUInt(1000000000000000)
// options.to = coldWalletAddress
// var intermediateSend = coldWalletContract?.method(options: options)
// let nonce = try await(web3.getNonce(sender, network: .Rinkeby))
// try intermediateSend?.setNonce(nonce!, network: .Rinkeby)
// let gasPrice = try await((intermediateSend?.estimateGas(options, network: .Rinkeby))!)
// print(gasPrice)
// intermediateSend = try ks!.signIntermediate(intermediate: intermediateSend!, password: "BANKEXFOUNDATION", network: .Rinkeby)
// let derivedSender = intermediateSend?.transaction.sender
// if (derivedSender?.address != sender.address) {
// print(derivedSender!.address)
// print(sender.address)
// print("Address mismatch")
//// return
// }
// let res = try await((intermediateSend?.send(network: .Rinkeby))!)
// print(res)

let coldWalletABI = "[{\"payable\":true,\"type\":\"fallback\"}]"
let coldWalletAddress = EthereumAddress("0x6394b37Cf80A7358b38068f0CA4760ad49983a1B")
let addressSanity = ks?.address
if addressSanity!.address != sender.address {
print("Addresses mismatch")
}
let coldWalletContract = web3.contract(coldWalletABI, at: coldWalletAddress)
options = Web3Options()
options = Web3Options.defaultOptions()
options.gas = BigUInt(21000)
options.from = ks?.address!
options.value = BigUInt(1000000000000000)

var intermediateSend = coldWalletContract?.method(options: options)
let gasPrice = try await((web3.contract(coldWalletABI, at: coldWalletAddress)?.method(options: options)?.estimateGas(options: nil, network: .Rinkeby))!)
let nonce = try await(web3.getNonce(sender, network: .Rinkeby))
var intermediateSend = web3.contract(coldWalletABI, at: coldWalletAddress)?.method(options: options)
try intermediateSend?.setNonce(nonce!, network: .Rinkeby)
intermediateSend = try ks!.signIntermediate(intermediate: intermediateSend!, password: "BANKEXFOUNDATION", network: .Rinkeby)
let derivedSender = intermediateSend?.transaction.sender
if (derivedSender?.address != sender.address) {
print(derivedSender!.address)
print(sender.address)
print("Address mismatch")
// return
// return
}
let res = try await((intermediateSend?.send(network: .Rinkeby))!)
print(res)


}
catch{
print(error)
Expand Down
23 changes: 9 additions & 14 deletions web3swift/Contract/Classes/Contract.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public struct Contract {
}
return toReturn
}
var options: Web3Options = Web3Options()
var options: Web3Options? = Web3Options.defaultOptions()
var chainID: BigUInt = BigUInt(1)

public init(abi: [ABIElement]) {
Expand All @@ -40,37 +40,32 @@ public struct Contract {

public func method(_ method:String = "fallback", parameters: [AnyObject] = [AnyObject](), nonce: BigUInt = BigUInt(0), extraData: Data = Data(), options: Web3Options?, toAddress:EthereumAddress? = nil) -> EthereumTransaction? {
var to:EthereumAddress
if let toInOptions = toAddress, toInOptions.isValid {
to = toInOptions
} else if let toInDefaults = self.address, toInDefaults.isValid {
to = toInDefaults
let mergedOptions = Web3Options.merge(self.options, with: options)
if let toFound = toAddress, toFound.isValid {
to = toFound
} else if let toFound = mergedOptions?.to, toFound.isValid {
to = toFound
} else {
return nil
}

var gas:BigUInt
if let gasInOptions = options?.gas, gasInOptions > BigUInt(0) {
if let gasInOptions = mergedOptions?.gas, gasInOptions > BigUInt(0) {
gas = gasInOptions
} else if let gasInDefaults = self.options.gas, gasInDefaults > BigUInt(0) {
gas = gasInDefaults
} else {
return nil
}

var gasPrice:BigUInt
if let gasPriceInOptions = options?.gasPrice, gasPriceInOptions > BigUInt(0) {
if let gasPriceInOptions = mergedOptions?.gasPrice, gasPriceInOptions > BigUInt(0) {
gasPrice = gasPriceInOptions
} else if let gasPriceInDefaults = self.options.gasPrice, gasPriceInDefaults > BigUInt(0) {
gasPrice = gasPriceInDefaults
} else {
return nil
}

var value:BigUInt
if let valueInOptions = options?.value {
if let valueInOptions = mergedOptions?.value {
value = valueInOptions
} else if let valueInDefaults = self.options.value {
value = valueInDefaults
} else {
value = BigUInt(0)
}
Expand Down
45 changes: 34 additions & 11 deletions web3swift/Contract/Classes/Web3+Contract.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//

// Web3+Contract.swift
// web3swift
//
Expand All @@ -21,20 +21,27 @@ extension web3 {
public struct web3contract {
var contract: Contract
var provider: Web3Provider
public init?(_ prov: Web3Provider, abiString: String, at: EthereumAddress? = nil, options: Web3Options? = nil){
public var options: Web3Options? = Web3Options.defaultOptions()

public init?(_ provider: Web3Provider, abiString: String, at: EthereumAddress? = nil, options: Web3Options? = nil) {
do {
provider = prov
self.provider = provider
let jsonData = abiString.data(using: .utf8)
let abi = try JSONDecoder().decode([ABIRecord].self, from: jsonData!)
let abiNative = try abi.map({ (record) -> ABIElement in
return try record.parse()
})
var mergedOptions = Web3Options.merge(self.options, with: options)
contract = Contract(abi: abiNative)
if at != nil {
contract.address = at
mergedOptions?.to = at
} else if let addr = mergedOptions?.to {
contract.address = addr
}
if options != nil {
contract.options = options!
self.options = mergedOptions
if contract.address == nil {
return nil
}
}
catch{
Expand All @@ -48,6 +55,16 @@ extension web3 {
public var provider: Web3Provider
public var contract: Contract
public var method: String
public var options: Web3Options? = Web3Options.defaultOptions()

public init (transaction: EthereumTransaction, provider: Web3Provider, contract: Contract, method: String, options: Web3Options?) {
self.transaction = transaction
self.provider = provider
self.contract = contract
self.contract.options = options
self.method = method
self.options = options
}

public mutating func setNonce(_ nonce: BigUInt, network: Networks? = nil) throws {
self.transaction.nonce = nonce
Expand Down Expand Up @@ -77,7 +94,8 @@ extension web3 {
}
public func call(options: Web3Options?, network: Networks = .Mainnet) -> Promise<[String:Any]?> {
return async {
let res = try await(self.provider.call(transaction: self.transaction, options: options, network: network))
let mergedOptions = Web3Options.merge(self.options, with: options)
let res = try await(self.provider.call(transaction: self.transaction, options: mergedOptions, network: network))
if res == nil {
return nil
}
Expand All @@ -96,19 +114,24 @@ extension web3 {
}
public func estimateGas(options: Web3Options?, network: Networks = .Mainnet) -> Promise<BigUInt?> {
return async {
let res = try await(self.provider.estimateGas(transaction: self.transaction, options: options, network: network))
let mergedOptions = Web3Options.merge(self.options, with: options)
let res = try await(self.provider.estimateGas(transaction: self.transaction, options: mergedOptions, network: network))
if res == nil {
return nil
}
let gas = BigUInt(res!)
return gas
}
}

}
public func method(_ method:String = "fallback", parameters: [AnyObject] = [AnyObject](), nonce: BigUInt = BigUInt(0), extraData:Data = Data(), options: Web3Options?, toAddress:EthereumAddress? = nil) -> transactionIntermediate? {
guard let tx = self.contract.method(method, parameters: parameters, nonce: nonce, extraData:extraData, options: options, toAddress:toAddress) else {return nil}
return transactionIntermediate(transaction: tx, provider: self.provider, contract: self.contract, method: method)

public func method(_ method:String = "fallback", parameters: [AnyObject] = [AnyObject](), nonce: BigUInt = BigUInt(0), extraData:Data = Data(), options: Web3Options?) -> transactionIntermediate? {

let mergedOptions = Web3Options.merge(self.options, with: options)

guard let tx = self.contract.method(method, parameters: parameters, nonce: nonce, extraData:extraData, options: mergedOptions, toAddress:self.contract.address) else {return nil}
let intermediate = transactionIntermediate(transaction: tx, provider: self.provider, contract: self.contract, method: method, options: mergedOptions)
return intermediate
}
}
}
16 changes: 11 additions & 5 deletions web3swift/Contract/Classes/Web3+Infura.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,13 @@ public struct InfuraProvider:Web3Provider {

public func estimateGas(transaction: EthereumTransaction, options: Web3Options?, network: Networks) -> Promise<BigUInt?> {
return async {
guard let req = EthereumTransaction.createRequest(method: "eth_estimageGas", transaction: transaction, onBlock: "latest", options: options) else {return nil}
let response = try await(self.postToInfura(req, network: network)!)
// print(response)
guard let req = EthereumTransaction.createRequest(method: "eth_estimateGas", transaction: transaction, onBlock: "latest", options: options) else {return nil}
var infuraReq = req
let params = [req.params?.params[0]] as Array<Encodable>
let pars = JSONRPCparams(params: params)
infuraReq.params = pars
let response = try await(self.postToInfura(infuraReq, network: network)!)
print(response)
guard let res = response as? [String: Any], let resultString = res["result"] as? String else {return nil}
guard let biguint = BigUInt(resultString.stripHexPrefix(), radix: 16) else {return nil}
return biguint
Expand All @@ -74,7 +78,7 @@ public struct InfuraProvider:Web3Provider {
req.serializedParams = serialized
req.params = pars
let response = try await(self.postToInfura(req, network: network)!)
// print(response)
print(response)
guard let res = response as? [String: Any], let resultString = res["result"] as? String else {return nil}
guard let biguint = BigUInt(resultString.stripHexPrefix(), radix: 16) else {return nil}
return biguint
Expand All @@ -98,7 +102,9 @@ public struct InfuraProvider:Web3Provider {
if self.accessToken != nil {
requestURL = requestURL + self.accessToken!
}
guard let _ = try? JSONEncoder().encode(request) else {return nil}
var cleanedRequest = request
cleanedRequest.serializedParams = nil
guard let _ = try? JSONEncoder().encode(cleanedRequest) else {return nil}
// print(String(data: requestJSON, encoding: .utf8))
let headers: HTTPHeaders = [
"Content-Type": "application/json",
Expand Down
46 changes: 43 additions & 3 deletions web3swift/Contract/Classes/Web3.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,51 @@ public enum Networks {
public struct Web3Options {
public var to: EthereumAddress? = nil
public var from: EthereumAddress? = nil
public var gas: BigUInt? = BigUInt(21000)
public var gasPrice: BigUInt? = BigUInt(5000000000)
public var value: BigUInt? = BigUInt(0)
public var gas: BigUInt? = nil
public var gasPrice: BigUInt? = nil
public var value: BigUInt? = nil
public init() {
}
public static func defaultOptions() -> Web3Options{
var options = Web3Options()
options.gas = BigUInt(21000)
options.gasPrice = BigUInt(5000000000)
options.value = BigUInt(0)
return options
}

public static func merge(_ options:Web3Options?, with other:Web3Options?) -> Web3Options? {
if (other == nil && options == nil) {
return Web3Options.defaultOptions()
}
var newOptions = Web3Options.defaultOptions()
if (other?.to != nil) {
newOptions.to = other?.to
} else {
newOptions.to = options?.to
}
if (other?.from != nil) {
newOptions.from = other?.from
} else {
newOptions.from = options?.from
}
if (other?.gas != nil) {
newOptions.gas = other?.gas
} else {
newOptions.gas = options?.gas
}
if (other?.gasPrice != nil) {
newOptions.gasPrice = other?.gasPrice
} else {
newOptions.gasPrice = options?.gasPrice
}
if (other?.value != nil) {
newOptions.value = other?.value
} else {
newOptions.value = options?.value
}
return newOptions
}
}

struct JSONRPCrequest: Encodable, ParameterEncoding {
Expand Down
2 changes: 2 additions & 0 deletions web3swift/Transaction/Classes/EthereumTransaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ public struct EthereumTransaction: CustomStringConvertible {
params.value = valueEncoding.head?.toHexString().addHexPrefix().stripLeadingZeroes()
if (self.data != Data()) {
params.data = self.data.toHexString().addHexPrefix()
} else {
params.data = "0x"
}
return params
}
Expand Down

0 comments on commit 0980217

Please sign in to comment.