Skip to content

Feature Request: Creating a wrapper to expose the client methods using async await #27

@Vilijan

Description

@Vilijan

Using the latest Swift's practices for Concurrency will make the code that is using the Swift-Algorand-SDK a lot more readable. The idea would be to create a wrapper on top of the current methods that use the async await syntax instead of competition handlers.

A sample example implementation of some of the most common methods:

func suggestedParameters() async throws -> TransactionParametersResponse {
        return try await withCheckedThrowingContinuation({ continuation in
            DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
                self.client.transactionParams().execute(){ paramResponse in
                    if(!(paramResponse.isSuccessful)){
                        continuation.resume(throwing: GeneralError.error)
                    } else {
                        continuation.resume(returning: paramResponse.data!)
                    }
                }
            }
        })
    }
 
 func waitForConfirmation(transactionID: String) async throws -> String {
        return try await withCheckedThrowingContinuation({ continuation in
            DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
                self.client.pendingTransactionInformation(txId: transactionID).execute() { response in
                    if(response.isSuccessful){
                        continuation.resume(returning: transactionID)
                    }else{
                        continuation.resume(throwing: GeneralError.error)
                    }
                }
            }
        })
 }
 
 func executeTransaction(encodedTransaction: [Int8]) async throws -> String {
        let transactionID: String = try await withCheckedThrowingContinuation({ continuation in
            DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
                self.client.rawTransaction(rawtxn: encodedTransaction).execute(){ response in
                    if(response.isSuccessful){
                        continuation.resume(returning: response.data!.txId)
                    }else{
                        continuation.resume(throwing: GeneralError.error)
                    }
 
                }
            }
        })
 
        return try await waitForConfirmation(transactionID: transactionID)
   }

Then we can use those methods, which makes the code a lot more readable.
Sample of creating new asset:

let account = try! Account()

let suggestedParams = try await self.suggestedParameters()
 
let create_asa_txn = try! Transaction.assetCreateTransactionBuilder()
              .setSender(sdk_account.address)
              .setAssetTotal(assetTotal: 1)
              .setAssetDecimals(assetDecimals:  0)
              .assetUnitName(assetUnitName: "APPL")
              .assetName(assetName:  "Swift SDK")
              .manager(manager: sdk_account.address)
              .reserve(reserve: sdk_account.address)
              .defaultFrozen(defaultFrozen:  false)
              .suggestedParams(params: suggestedParams)
              .build()
 
 let signedTransaction = account.signTransaction(tx: create_asa_txn)
 
 let transactionID =  try await self.executeTransaction(encodedTransaction: CustomEncoder.encodeToMsgPack(signedTransaction))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions