Skip to content

Commit

Permalink
changes
Browse files Browse the repository at this point in the history
  • Loading branch information
matiasbzurovski committed Oct 17, 2024
1 parent 12cb70b commit 12c7d30
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ struct GatewayAPIClient: Sendable, DependencyKey {
var getAccountLockerVaults: GetAccountLockerVaults

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

// MARK: - Transaction
typealias TransactionPreview = @Sendable (GatewayAPI.TransactionPreviewRequest) async throws -> GatewayAPI.TransactionPreviewResponse
typealias StreamTransactions = @Sendable (GatewayAPI.StreamTransactionsRequest) async throws -> GatewayAPI.StreamTransactionsResponse
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

var errorDescription: String? {
Expand Down
127 changes: 44 additions & 83 deletions RadixWallet/Clients/TransactionClient/TransactionClient+Live.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ extension TransactionClient {
}

return .init(
notaryPublicKey: request.ephemeralNotaryPublicKey,
notaryKey: request.ephemeralNotaryKey,
intentSigning: intentSigning
)
}
Expand Down Expand Up @@ -123,18 +123,18 @@ extension TransactionClient {
startEpochInclusive: epoch,
endEpochExclusive: epoch + request.makeTransactionHeaderInput.epochWindow,
nonce: request.nonce,
notaryPublicKey: Sargon.PublicKey.ed25519(request.transactionSigners.notaryPublicKey.intoSargon()),
notaryKey: Sargon.Key.ed25519(request.transactionSigners.notaryKey.intoSargon()),
notaryIsSignatory: request.transactionSigners.notaryIsSignatory,
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
let signedTransactionIntent = SignedIntent(
intent: request.transactionIntent,
intentSignatures: IntentSignatures(signatures: Array(request.intentSignatures.map { IntentSignature(signatureWithPublicKey: $0) }))
intentSignatures: IntentSignatures(signatures: Array(request.intentSignatures.map { IntentSignature(signatureWithKey: $0) }))
)

let signedIntentHash = signedTransactionIntent.hash()
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,
notaryKey: .ed25519(request.ephemeralNotaryKey.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,
ephemeralNotaryPublicKey: request.ephemeralNotaryPublicKey
manifest: preview.transactionManifest,
ephemeralNotaryKey: request.ephemeralNotaryKey
))

/// 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 @@ -342,7 +311,7 @@ extension TransactionClient {
feeIncludingCandidate.updateSignaturesCost(signingFactors.expectedSignatureCount)
if candidate.xrdBalance >= feeIncludingCandidate.totalFee.max {
let signers = TransactionSigners(
notaryPublicKey: request.transactionSigners.notaryPublicKey,
notaryKey: request.transactionSigners.notaryKey,
intentSigning: .intentSigners(.init(rawValue: .init(signerEntities))!)
)
return .init(
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 12c7d30

Please sign in to comment.