diff --git a/Sources/Core/EthereumABI/ABIElements.swift b/Sources/Core/EthereumABI/ABIElements.swift index ac111458b..bb269b9c5 100755 --- a/Sources/Core/EthereumABI/ABIElements.swift +++ b/Sources/Core/EthereumABI/ABIElements.swift @@ -202,7 +202,7 @@ extension ABI.Element.Function { /// Encode parameters of a given contract method /// - Parameter parameters: Parameters to pass to Ethereum contract - /// - Returns: Encoded data + /// - Returns: Encoded data public func encodeParameters(_ parameters: [AnyObject]) -> Data? { guard parameters.count == inputs.count, let data = ABIEncoder.encode(types: inputs, values: parameters) else { return nil } @@ -325,7 +325,7 @@ extension ABI.Element.Function { // set a flag to detect the request succeeded } - if returnArray.isEmpty { + if returnArray.isEmpty && !outputs.isEmpty { return nil } diff --git a/Sources/web3swift/Operations/WriteOperation.swift b/Sources/web3swift/Operations/WriteOperation.swift index 9c84202e7..6458ba6ff 100755 --- a/Sources/web3swift/Operations/WriteOperation.swift +++ b/Sources/web3swift/Operations/WriteOperation.swift @@ -11,25 +11,35 @@ import Core public class WriteOperation: ReadOperation { // FIXME: Rewrite this to CodableTransaction - /// Sends raw transaction for write operation. + /// Sends signed or unsigned transaction for write operation. /// - Parameters: - /// - password: Password for private key. - /// - policies: Custom policies for how to resolve (optional). Default is auto. - public func writeToChain(password: String, policies: Policies = .auto) async throws -> TransactionSendingResult { + /// - password: Password for the private key in the keystore manager attached to the provider + /// you set to `web3` passed in the initializer. + /// - policies: Determining the behaviour of how transaction attributes like gas limit and + /// nonce are resolved. Default value is ``Policies/auto``. + /// - sendRaw: If set to `true` transaction will be signed and sent using `eth_sendRawTransaction`. + /// Otherwise, no signing attempts will take place and the `eth_sendTransaction` RPC will be used instead. + /// Default value is `true`. + public func writeToChain(password: String, policies: Policies = .auto, sendRaw: Bool = true) async throws -> TransactionSendingResult { try await policyResolver.resolveAll(for: &transaction, with: policies) - if let attachedKeystoreManager = self.web3.provider.attachedKeystoreManager { - do { - try Web3Signer.signTX(transaction: &transaction, - keystore: attachedKeystoreManager, - account: transaction.from ?? transaction.sender ?? EthereumAddress.contractDeploymentAddress(), - password: password) - } catch { - throw Web3Error.inputError(desc: "Failed to locally sign a transaction") - } - guard let transactionData = transaction.encode(for: .transaction) else { throw Web3Error.dataError } - return try await web3.eth.send(raw: transactionData) + + guard sendRaw else { + return try await web3.eth.send(transaction) + } + + guard let attachedKeystoreManager = web3.provider.attachedKeystoreManager else { + throw Web3Error.inputError(desc: "Failed to locally sign a transaction. Web3 provider doesn't have keystore attached.") + } + + do { + try Web3Signer.signTX(transaction: &transaction, + keystore: attachedKeystoreManager, + account: transaction.from ?? transaction.sender ?? EthereumAddress.contractDeploymentAddress(), + password: password) + } catch { + throw Web3Error.inputError(desc: "Failed to locally sign a transaction. \(error.localizedDescription)") } - // MARK: Sending Data flow - return try await web3.eth.send(transaction) + guard let transactionData = transaction.encode(for: .transaction) else { throw Web3Error.dataError } + return try await web3.eth.send(raw: transactionData) } } diff --git a/Tests/web3swiftTests/localTests/AdvancedABIv2Tests.swift b/Tests/web3swiftTests/localTests/AdvancedABIv2Tests.swift index f31eaf1ac..e34aed0f8 100755 --- a/Tests/web3swiftTests/localTests/AdvancedABIv2Tests.swift +++ b/Tests/web3swiftTests/localTests/AdvancedABIv2Tests.swift @@ -25,7 +25,7 @@ class AdvancedABIv2Tests: LocalTestCase { deployTx.transaction.from = allAddresses[0] // MARK: Sending Data flow let policies = Policies(gasLimitPolicy: .manual(3000000)) - let result = try await deployTx.writeToChain(password: "web3swift", policies: policies) + let result = try await deployTx.writeToChain(password: "web3swift", policies: policies, sendRaw: false) let txHash = result.hash.stripHexPrefix() Thread.sleep(forTimeInterval: 1.0) @@ -61,7 +61,7 @@ class AdvancedABIv2Tests: LocalTestCase { let deployTx = contract.prepareDeploy(bytecode: bytecode, parameters: parameters)! deployTx.transaction.from = allAddresses[0] let policies = Policies(gasLimitPolicy: .manual(3000000)) - let result = try await deployTx.writeToChain(password: "web3swift", policies: policies) + let result = try await deployTx.writeToChain(password: "web3swift", policies: policies, sendRaw: false) let txHash = result.hash.stripHexPrefix() Thread.sleep(forTimeInterval: 1.0) @@ -97,7 +97,7 @@ class AdvancedABIv2Tests: LocalTestCase { let deployTx = contract.prepareDeploy(bytecode: bytecode, parameters: parameters)! deployTx.transaction.from = allAddresses[0] let policies = Policies(gasLimitPolicy: .manual(3000000)) - let result = try await deployTx.writeToChain(password: "web3swift", policies: policies) + let result = try await deployTx.writeToChain(password: "web3swift", policies: policies, sendRaw: false) let txHash = result.hash.stripHexPrefix() Thread.sleep(forTimeInterval: 1.0) @@ -132,7 +132,7 @@ class AdvancedABIv2Tests: LocalTestCase { let deployTx = contract.prepareDeploy(bytecode: bytecode, parameters: parameters)! deployTx.transaction.from = allAddresses[0] let policies = Policies(gasLimitPolicy: .manual(3000000)) - let result = try await deployTx.writeToChain(password: "web3swift", policies: policies) + let result = try await deployTx.writeToChain(password: "web3swift", policies: policies, sendRaw: false) let txHash = result.hash.stripHexPrefix() Thread.sleep(forTimeInterval: 1.0) @@ -168,7 +168,7 @@ class AdvancedABIv2Tests: LocalTestCase { let deployTx = contract.prepareDeploy(bytecode: bytecode, parameters: parameters)! deployTx.transaction.from = allAddresses[0] let policies = Policies(gasLimitPolicy: .manual(3000000)) - let result = try await deployTx.writeToChain(password: "web3swift", policies: policies) + let result = try await deployTx.writeToChain(password: "web3swift", policies: policies, sendRaw: false) let txHash = result.hash.stripHexPrefix() Thread.sleep(forTimeInterval: 1.0) diff --git a/Tests/web3swiftTests/localTests/BasicLocalNodeTests.swift b/Tests/web3swiftTests/localTests/BasicLocalNodeTests.swift index bddfe6a1e..c099f330d 100755 --- a/Tests/web3swiftTests/localTests/BasicLocalNodeTests.swift +++ b/Tests/web3swiftTests/localTests/BasicLocalNodeTests.swift @@ -25,7 +25,7 @@ class BasicLocalNodeTests: LocalTestCase { let deployTx = contract.prepareDeploy(bytecode: bytecode, parameters: parameters)! deployTx.transaction.from = allAddresses[0] let policies = Policies(gasLimitPolicy: .manual(3000000)) - let result = try await deployTx.writeToChain(password: "web3swift", policies: policies) + let result = try await deployTx.writeToChain(password: "web3swift", policies: policies, sendRaw: false) let txHash = result.hash.stripHexPrefix() while true { @@ -60,7 +60,7 @@ class BasicLocalNodeTests: LocalTestCase { print("Balance before to: " + balanceBeforeTo.description) print("Balance before from: " + balanceBeforeFrom.description) - let result = try await sendTx.writeToChain(password: "web3swift") + let result = try await sendTx.writeToChain(password: "web3swift", sendRaw: false) let txHash = Data.fromHex(result.hash.stripHexPrefix())! Thread.sleep(forTimeInterval: 1.0) diff --git a/Tests/web3swiftTests/localTests/ERC20ClassTests.swift b/Tests/web3swiftTests/localTests/ERC20ClassTests.swift index 339e0c181..2e7d6f945 100755 --- a/Tests/web3swiftTests/localTests/ERC20ClassTests.swift +++ b/Tests/web3swiftTests/localTests/ERC20ClassTests.swift @@ -40,7 +40,7 @@ class ERC20ClassTests: LocalTestCase { func testERC20tokenBalanceAndAllowance() async throws { let (web3, _, receipt, _) = try await TestHelpers.localDeployERC20() - let erc20token = ERC20.init(web3: web3, provider: web3.provider, address: receipt.contractAddress!) + let erc20token = ERC20(web3: web3, provider: web3.provider, address: receipt.contractAddress!) let userAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")! diff --git a/Tests/web3swiftTests/localTests/LocalTestCase.swift b/Tests/web3swiftTests/localTests/LocalTestCase.swift index 720d01f35..c44dab412 100644 --- a/Tests/web3swiftTests/localTests/LocalTestCase.swift +++ b/Tests/web3swiftTests/localTests/LocalTestCase.swift @@ -30,7 +30,7 @@ class LocalTestCase: XCTestCase { writeTX.transaction.value = value let policies = Policies(gasLimitPolicy: .manual(78423), gasPricePolicy: .manual(20000000000)) for _ in block..<25 { - _ = try! await writeTX.writeToChain(password: "", policies: policies) + _ = try! await writeTX.writeToChain(password: "", policies: policies, sendRaw: false) } } } diff --git a/Tests/web3swiftTests/localTests/PersonalSignatureTests.swift b/Tests/web3swiftTests/localTests/PersonalSignatureTests.swift index e9b99f965..418ff7a22 100755 --- a/Tests/web3swiftTests/localTests/PersonalSignatureTests.swift +++ b/Tests/web3swiftTests/localTests/PersonalSignatureTests.swift @@ -42,7 +42,7 @@ class PersonalSignatureTests: XCTestCase { let allAddresses = try await web3.eth.ownedAccounts() deployTx.transaction.from = allAddresses[0] let policies = Policies(gasLimitPolicy: .manual(3000000)) - let deployResult = try await deployTx.writeToChain(password: "web3swift", policies: policies) + let deployResult = try await deployTx.writeToChain(password: "web3swift", policies: policies, sendRaw: false) let txHash = Data.fromHex(deployResult.hash.stripHexPrefix())! Thread.sleep(forTimeInterval: 1.0) diff --git a/Tests/web3swiftTests/localTests/TestHelpers.swift b/Tests/web3swiftTests/localTests/TestHelpers.swift index 23ad080a3..c80b4435e 100644 --- a/Tests/web3swiftTests/localTests/TestHelpers.swift +++ b/Tests/web3swiftTests/localTests/TestHelpers.swift @@ -33,7 +33,7 @@ class TestHelpers { parameters: parameters)! deployTx.transaction.from = allAddresses[0] let policies = Policies(gasLimitPolicy: .manual(3000000)) - let result = try await deployTx.writeToChain(password: "web3swift", policies: policies) + let result = try await deployTx.writeToChain(password: "web3swift", policies: policies, sendRaw: false) let txHash = Data.fromHex(result.hash.stripHexPrefix())! Thread.sleep(forTimeInterval: 1.0) diff --git a/Tests/web3swiftTests/localTests/TransactionsTests.swift b/Tests/web3swiftTests/localTests/TransactionsTests.swift index 893e3b13c..b7e1a6886 100755 --- a/Tests/web3swiftTests/localTests/TransactionsTests.swift +++ b/Tests/web3swiftTests/localTests/TransactionsTests.swift @@ -638,7 +638,7 @@ class TransactionsTests: XCTestCase { writeTX.transaction.from = from writeTX.transaction.value = value! let policies = Policies(gasLimitPolicy: .manual(78423)) - let result = try await writeTX.writeToChain(password: "", policies: policies) + let result = try await writeTX.writeToChain(password: "", policies: policies, sendRaw: false) let txHash = Data.fromHex(result.hash.stripHexPrefix())! print("Transaction with hash ", txHash) diff --git a/Tests/web3swiftTests/localTests/UserCases.swift b/Tests/web3swiftTests/localTests/UserCases.swift index e353fb990..1f930783d 100755 --- a/Tests/web3swiftTests/localTests/UserCases.swift +++ b/Tests/web3swiftTests/localTests/UserCases.swift @@ -76,11 +76,11 @@ class UserCases: XCTestCase { let allAddresses = try await web3.eth.ownedAccounts() let contract = web3.contract(Web3.Utils.estimateGasTestABI, at: nil, abiVersion: 2)! - let parameters = [] as [AnyObject] + let parameters = [AnyObject]() let deployTx = contract.prepareDeploy(bytecode: bytecode, parameters: parameters)! deployTx.transaction.from = allAddresses[0] let policies = Policies(gasLimitPolicy: .manual(3000000)) - let result = try await deployTx.writeToChain(password: "web3swift", policies: policies) + let result = try await deployTx.writeToChain(password: "web3swift", policies: policies, sendRaw: false) let txHash = Data.fromHex(result.hash.stripHexPrefix())! Thread.sleep(forTimeInterval: 1.0)