Skip to content

Commit

Permalink
use Sargon
Browse files Browse the repository at this point in the history
handle errors

code deletion

fix
  • Loading branch information
matiasbzurovski committed Oct 17, 2024
1 parent e531590 commit c8f8845
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ public struct GatewayAPIClient: Sendable, DependencyKey {
public var getAccountLockerVaults: GetAccountLockerVaults

// MARK: Transaction
public var transactionPreview: TransactionPreview
public var streamTransactions: StreamTransactions
public var prevalidateDeposit: PrevalidateDeposit
}
Expand Down Expand Up @@ -56,7 +55,6 @@ extension GatewayAPIClient {
public typealias GetAccountLockerVaults = @Sendable (GatewayAPI.StateAccountLockerPageVaultsRequest) async throws -> GatewayAPI.StateAccountLockerPageVaultsResponse

// MARK: - Transaction
public typealias TransactionPreview = @Sendable (GatewayAPI.TransactionPreviewRequest) async throws -> GatewayAPI.TransactionPreviewResponse
public typealias StreamTransactions = @Sendable (GatewayAPI.StreamTransactionsRequest) async throws -> GatewayAPI.StreamTransactionsResponse
public typealias PrevalidateDeposit = @Sendable (GatewayAPI.AccountDepositPreValidationRequest) async throws -> GatewayAPI.AccountDepositPreValidationResponse
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,6 @@ extension GatewayAPIClient {
request: request
) { $0.appendingPathComponent("/state/account-locker/page/vaults") }
},
transactionPreview: { transactionPreviewRequest in
try await post(
request: transactionPreviewRequest
) { $0.appendingPathComponent("transaction/preview") }
},
streamTransactions: { streamTransactionsRequest in
try await post(
request: streamTransactionsRequest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ extension GatewayAPIClient: TestDependencyKey {
getNonFungibleData: unimplemented("\(Self.self).getNonFungibleData"),
getAccountLockerTouchedAt: unimplemented("\(Self.self).getAccountLockerTouchedAt"),
getAccountLockerVaults: unimplemented("\(Self.self).GetAccountLockerVaults"),
transactionPreview: unimplemented("\(Self.self).transactionPreview"),
streamTransactions: unimplemented("\(Self.self).streamTransactions"),
prevalidateDeposit: unimplemented("\(Self.self).prevalidateDeposit")
)
Expand All @@ -42,7 +41,6 @@ extension GatewayAPIClient: TestDependencyKey {
getNonFungibleData: unimplemented("\(self).getNonFungibleData"),
getAccountLockerTouchedAt: unimplemented("\(Self.self).getAccountLockerTouchedAt"),
getAccountLockerVaults: unimplemented("\(Self.self).GetAccountLockerVaults"),
transactionPreview: unimplemented("\(self).transactionPreview"),
streamTransactions: unimplemented("\(self).streamTransactions"),
prevalidateDeposit: unimplemented("\(Self.self).prevalidateDeposit")
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ extension TransactionFailure {
case failedToRetrieveTXReceipt(String)
case failedToExtractTXReceiptBytes
case failedToGenerateTXReview(Error)
case manifestWithReservedInstructions([ReservedInstruction])
case manifestWithReservedInstructions(String)
case oneOfRecevingAccountsDoesNotAllowDeposits

public var errorDescription: String? {
Expand Down
117 changes: 39 additions & 78 deletions RadixWallet/Clients/TransactionClient/TransactionClient+Live.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ extension TransactionClient {
tipPercentage: request.makeTransactionHeaderInput.tipPercentage
)

return .init(header: header, manifest: request.manifest, message: request.message ?? Message.none)
return .init(header: header, manifest: request.manifest, message: request.message)
}

let notarizeTransaction: NotarizeTransaction = { request in
Expand All @@ -155,43 +155,35 @@ extension TransactionClient {
)
}

@Sendable
func analyseTransactionPreview(request: ManifestReviewRequest) async throws -> Sargon.TransactionToReview {
do {
return try await SargonOS.shared.analyseTransactionPreview(
instructions: request.unvalidatedManifest.transactionManifestString,
blobs: request.unvalidatedManifest.blobs,
message: request.message,
isWalletTransaction: request.isWalletTransaction,
nonce: request.nonce,
notaryPublicKey: .ed25519(request.ephemeralNotaryPublicKey.intoSargon())
)
} catch {
throw TransactionFailure.fromCommonError(error as? CommonError)
}
}

let getTransactionReview: GetTransactionReview = { request in
let networkID = await gatewaysClient.getCurrentNetworkID()
// Get preview from SargonOS
let preview = try await analyseTransactionPreview(request: request)

let manifestToSign = try request.unvalidatedManifest.transactionManifest(onNetwork: networkID)
let networkID = await gatewaysClient.getCurrentNetworkID()

/// Get all transaction signers.
let transactionSigners = try await getTransactionSigners(.init(
networkID: networkID,
manifest: manifestToSign,
manifest: preview.transactionManifest,
ephemeralNotaryPublicKey: request.ephemeralNotaryPublicKey
))

/// Get the transaction preview
let transactionPreviewRequest = try await createTransactionPreviewRequest(
for: request,
networkID: networkID,
transactionManifest: manifestToSign,
transactionSigners: transactionSigners
)
let transactionPreviewResponse = try await gatewayAPIClient.transactionPreview(transactionPreviewRequest)
guard transactionPreviewResponse.receipt.status == .succeeded else {
throw TransactionFailure.fromFailedTXReviewResponse(transactionPreviewResponse)
}
guard let engineToolkitReceipt = transactionPreviewResponse.engineToolkitReceipt else {
throw TransactionFailure.failedToPrepareTXReview(.failedToExtractTXReceiptBytes)
}

/// Analyze the manifest
let analyzedManifestToReview = try manifestToSign.executionSummary(
engineToolkitReceipt: engineToolkitReceipt
)

/// Transactions created outside of the Wallet are not allowed to use reserved instructions
if !request.isWalletTransaction, !analyzedManifestToReview.reservedInstructions.isEmpty {
throw TransactionFailure.failedToPrepareTXReview(.manifestWithReservedInstructions(analyzedManifestToReview.reservedInstructions))
}

/// Get all of the expected signing factors.
let signingFactors = try await {
if let nonEmpty = NonEmpty<Set<AccountOrPersona>>(transactionSigners.intentSignerEntitiesOrEmpty()) {
Expand All @@ -207,7 +199,7 @@ extension TransactionClient {
/// If notary is signatory, count the signature of the notary that will be added.
let signaturesCount = transactionSigners.notaryIsSignatory ? 1 : signingFactors.expectedSignatureCount
var transactionFee = try TransactionFee(
executionSummary: analyzedManifestToReview,
executionSummary: preview.executionSummary,
signaturesCount: signaturesCount,
notaryIsSignatory: transactionSigners.notaryIsSignatory,
includeLockFee: false // Calculate without LockFee cost. It is yet to be determined if LockFe will be added or not
Expand All @@ -222,38 +214,15 @@ extension TransactionClient {
}

return TransactionToReview(
transactionManifest: manifestToSign,
analyzedManifestToReview: analyzedManifestToReview,
transactionManifest: preview.transactionManifest,
analyzedManifestToReview: preview.executionSummary,
networkID: networkID,
transactionFee: transactionFee,
transactionSigners: transactionSigners,
signingFactors: signingFactors
)
}

@Sendable
func createTransactionPreviewRequest(
for request: ManifestReviewRequest,
networkID: NetworkID,
transactionManifest: TransactionManifest,
transactionSigners: TransactionSigners
) async throws -> GatewayAPI.TransactionPreviewRequest {
let intent = try await buildTransactionIntent(.init(
networkID: networkID,
manifest: transactionManifest,
message: request.message,
nonce: request.nonce,
makeTransactionHeaderInput: request.makeTransactionHeaderInput,
transactionSigners: transactionSigners
))

return try .init(
rawManifest: transactionManifest,
header: intent.header,
transactionSigners: transactionSigners
)
}

let myInvolvedEntities: MyInvolvedEntities = { manifest in
let networkID = await gatewaysClient.getCurrentNetworkID()
return try await myEntitiesInvolvedInTransaction(
Expand Down Expand Up @@ -380,30 +349,22 @@ extension TransactionClient {
}

extension TransactionFailure {
static func fromFailedTXReviewResponse(_ response: GatewayAPI.TransactionPreviewResponse) -> Self {
let message = response.receipt.errorMessage ?? "Unknown reason"

// Quite rudimentary, but it is not worth making something smarter,
// as the GW will provide in the future strongly typed errors
let isFailureDueToDepositRules = message.contains("AccountError(DepositIsDisallowed") ||
message.contains("AccountError(NotAllBucketsCouldBeDeposited")

if isFailureDueToDepositRules {
return .failedToPrepareTXReview(.oneOfRecevingAccountsDoesNotAllowDeposits)
} else {
return .failedToPrepareTXReview(.failedToRetrieveTXReceipt(message))
}
}
}
static func fromCommonError(_ commonError: CommonError?) -> Self {
switch commonError {
case let .ReservedInstructionsNotAllowedInManifest(reservedInstructions):
.failedToPrepareTXReview(.manifestWithReservedInstructions(reservedInstructions))

private extension GatewayAPI.TransactionPreviewResponse {
var engineToolkitReceipt: String? {
guard
let dictionary = radixEngineToolkitReceipt?.value as? [String: Any],
let data = try? JSONSerialization.data(withJSONObject: dictionary, options: [])
else {
return nil
case .OneOfReceivingAccountsDoesNotAllowDeposits:
.failedToPrepareTXReview(.oneOfRecevingAccountsDoesNotAllowDeposits)

case .FailedTransactionPreview:
.failedToPrepareTXReview(.failedToRetrieveTXReceipt("Unknown reason"))

case .FailedToExtractTransactionReceiptBytes:
.failedToPrepareTXReview(.failedToExtractTXReceiptBytes)

default:
.failedToPrepareTXReview(.failedToRetrieveTXReceipt("Unknown reason"))
}
return String(data: data, encoding: .utf8)
}
}

0 comments on commit c8f8845

Please sign in to comment.