|
|
|
@ -4,10 +4,40 @@ import Foundation |
|
|
|
|
import PromiseKit |
|
|
|
|
import web3swift |
|
|
|
|
|
|
|
|
|
//TODO time to wrap `callSmartContract` with a class |
|
|
|
|
|
|
|
|
|
//TODO wrap callSmartContract() and cache into a type |
|
|
|
|
var smartContractCallsCache = [String: (promise: Promise<[String: Any]>, timestamp: Date)]() |
|
|
|
|
fileprivate var smartContractCallsCache = [String: (promise: Promise<[String: Any]>, timestamp: Date)]() |
|
|
|
|
|
|
|
|
|
fileprivate var web3s = [RPCServer: [TimeInterval: web3]]() |
|
|
|
|
|
|
|
|
|
func getCachedWeb3(forServer server: RPCServer, timeout: TimeInterval) throws -> web3 { |
|
|
|
|
if let result = web3s[server]?[timeout] { |
|
|
|
|
return result |
|
|
|
|
} else { |
|
|
|
|
guard let webProvider = Web3HttpProvider(server.rpcURL, network: server.web3Network) else { |
|
|
|
|
throw Web3Error(description: "Error creating web provider for: \(server.rpcURL) + \(server.web3Network)") |
|
|
|
|
} |
|
|
|
|
let configuration = webProvider.session.configuration |
|
|
|
|
configuration.timeoutIntervalForRequest = timeout |
|
|
|
|
configuration.timeoutIntervalForResource = timeout |
|
|
|
|
let session = URLSession(configuration: configuration) |
|
|
|
|
webProvider.session = session |
|
|
|
|
|
|
|
|
|
let result = web3swift.web3(provider: webProvider) |
|
|
|
|
if var timeoutsAndWeb3s = web3s[server] { |
|
|
|
|
timeoutsAndWeb3s[timeout] = result |
|
|
|
|
web3s[server] = timeoutsAndWeb3s |
|
|
|
|
} else { |
|
|
|
|
let timeoutsAndWeb3s: [TimeInterval: web3] = [timeout: result] |
|
|
|
|
web3s[server] = timeoutsAndWeb3s |
|
|
|
|
} |
|
|
|
|
return result |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func callSmartContract(withServer server: RPCServer, contract: AlphaWallet.Address, functionName: String, abiString: String, parameters: [AnyObject] = [AnyObject](), timeout: TimeInterval? = nil) -> Promise<[String: Any]> { |
|
|
|
|
let timeout: TimeInterval = 60 |
|
|
|
|
//We must include the ABI string in the key because the order of elements in a dictionary when serialized in the string is not ordered. Parameters (which is ordered) should ensure it's the same function |
|
|
|
|
let cacheKey = "\(contract).\(functionName) \(parameters) \(server.chainID)" |
|
|
|
|
let ttlForCache: TimeInterval = 10 |
|
|
|
@ -29,19 +59,11 @@ func callSmartContract(withServer server: RPCServer, contract: AlphaWallet.Addre |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let result: Promise<[String: Any]> = Promise { seal in |
|
|
|
|
let contractAddress = EthereumAddress(address: contract) |
|
|
|
|
guard let webProvider = Web3HttpProvider(server.rpcURL, network: server.web3Network) else { |
|
|
|
|
throw Web3Error(description: "Error creating web provider for: \(server.rpcURL) + \(server.web3Network)") |
|
|
|
|
} |
|
|
|
|
if let timeout = timeout { |
|
|
|
|
let configuration = webProvider.session.configuration |
|
|
|
|
configuration.timeoutIntervalForRequest = timeout |
|
|
|
|
configuration.timeoutIntervalForResource = timeout |
|
|
|
|
let session = URLSession(configuration: configuration) |
|
|
|
|
webProvider.session = session |
|
|
|
|
guard let web3 = try? getCachedWeb3(forServer: server, timeout: timeout) else { |
|
|
|
|
throw Web3Error(description: "Error creating web3 for: \(server.rpcURL) + \(server.web3Network)") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let web3 = web3swift.web3(provider: webProvider) |
|
|
|
|
let contractAddress = EthereumAddress(address: contract) |
|
|
|
|
|
|
|
|
|
guard let contractInstance = web3swift.web3.web3contract(web3: web3, abiString: abiString, at: contractAddress, options: web3.options) else { |
|
|
|
|
throw Web3Error(description: "Error creating web3swift contract instance to call \(functionName)()") |
|
|
|
@ -73,11 +95,10 @@ func getEventLogs( |
|
|
|
|
let contractAddress = EthereumAddress(address: contract) |
|
|
|
|
return .value(contractAddress) |
|
|
|
|
}.then { contractAddress -> Promise<[EventParserResultProtocol]> in |
|
|
|
|
guard let webProvider = Web3HttpProvider(server.rpcURL, network: server.web3Network) else { |
|
|
|
|
return Promise(error: Web3Error(description: "Error creating web provider for: \(server.rpcURL) + \(server.web3Network)")) |
|
|
|
|
guard let web3 = try? getCachedWeb3(forServer: server, timeout: 60) else { |
|
|
|
|
throw Web3Error(description: "Error creating web3 for: \(server.rpcURL) + \(server.web3Network)") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let web3 = web3swift.web3(provider: webProvider) |
|
|
|
|
guard let contractInstance = web3swift.web3.web3contract(web3: web3, abiString: abiString, at: contractAddress, options: web3.options) else { |
|
|
|
|
return Promise(error: Web3Error(description: "Error creating web3swift contract instance to call \(eventName)()")) |
|
|
|
|
} |
|
|
|
|