Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: transaction polling task #797

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions Sources/web3swift/Transaction/TransactionPollingTask.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// TransactionPollingTask.swift
//
// Created by JeneaVranceanu on 10.03.2023.
//

import Foundation
import Web3Core

/// Monitors a transaction's state on blockchain until transaction is completed successfully or not.
final public class TransactionPollingTask {

private enum DelayUnit: UInt64 {
case shortest = 1
case medium = 5
case longest = 60

func shouldIncreaseDelay(_ startTime: Date) -> Bool {
let timePassed = Date().timeIntervalSince1970 - startTime.timeIntervalSince1970
switch self {
case .shortest:
return timePassed > 10
case .medium:
return timePassed > 120
case .longest:
return false
}
}

var nextDelayUnit: DelayUnit {
switch self {
case .shortest:
return .medium
case .medium, .longest:
return .longest
}
}
}

public let transactionHash: Data

private let web3Instance: Web3
private var delayUnit: DelayUnit = .shortest

public init(transactionHash: Data, web3Instance: Web3) {
self.transactionHash = transactionHash
self.web3Instance = web3Instance
}

public func wait() async throws -> TransactionReceipt {
let startTime = Date()
while true {
let transactionReceipt = try await web3Instance.eth.transactionReceipt(transactionHash)

if transactionReceipt.status != .notYetProcessed {
return transactionReceipt
}

if delayUnit.shouldIncreaseDelay(startTime) {
delayUnit = delayUnit.nextDelayUnit
}

try await Task.sleep(nanoseconds: delayUnit.rawValue)
}
}
}
33 changes: 33 additions & 0 deletions Tests/web3swiftTests/localTests/TransactionPollingTaskTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// TransactionPollingTaskTest.swift
//
// Created by JeneaVranceanu on 10.03.2023.
//

import XCTest
import Foundation
@testable import web3swift
@testable import Web3Core

class TransactionPollingTaskTest: LocalTestCase {

func testTransactionPolling() async throws {
let web3 = try await Web3.new(LocalTestCase.url)
let sendToAddress = EthereumAddress("0xe22b8979739D724343bd002F9f432F5990879901")!
let allAddresses = try await web3.eth.ownedAccounts()
let contract = web3.contract(Web3.Utils.coldWalletABI, at: sendToAddress)
let writeTX = contract!.createWriteOperation("fallback")!
writeTX.transaction.from = allAddresses[0]
writeTX.transaction.value = 1

let policies = Policies(gasLimitPolicy: .automatic)
let result = try await writeTX.writeToChain(password: "", policies: policies, sendRaw: false)

let txHash = Data.fromHex(result.hash.stripHexPrefix())!

let transactionReceipt = try await TransactionPollingTask(transactionHash: txHash, web3Instance: web3).wait()

XCTAssertEqual(transactionReceipt.status, .ok)
}

}