From 180a85d807e3adf8a0dd0d0d9f4e89aa1a78a813 Mon Sep 17 00:00:00 2001 From: Maksim Zdobnikau <43750648+DelevoXDG@users.noreply.github.com> Date: Wed, 11 Oct 2023 12:24:51 +0200 Subject: [PATCH] Support pathfinder_getTransactionStatus (#106) --- .../Data/Transaction/Transaction.swift | 18 +++++++++--------- .../Data/Transaction/TransactionStatus.swift | 6 +++++- .../StarknetProvider/JsonRpcMethod.swift | 1 + .../StarknetProvider/JsonRpcParams.swift | 8 ++++++++ .../StarknetProvider/StarknetProvider.swift | 9 +++++++++ .../Providers/StarknetProviderProtocol.swift | 12 ++++++++++-- .../Crypto/TransactionStatusTests.swift | 19 +++++++++++++++++++ .../DevnetClient/DevnetClientModels.swift | 4 ++-- 8 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 Tests/StarknetTests/Crypto/TransactionStatusTests.swift diff --git a/Sources/Starknet/Data/Transaction/Transaction.swift b/Sources/Starknet/Data/Transaction/Transaction.swift index 77f53cd35..3b6cd008e 100644 --- a/Sources/Starknet/Data/Transaction/Transaction.swift +++ b/Sources/Starknet/Data/Transaction/Transaction.swift @@ -108,7 +108,7 @@ public struct StarknetInvokeTransactionV0: StarknetTransaction { self.maxFee = try container.decode(Felt.self, forKey: .maxFee) self.hash = try container.decodeIfPresent(Felt.self, forKey: .hash) - try verifyTransactionType(container: container, codingKeysType: Self.CodingKeys) + try verifyTransactionType(container: container, codingKeysType: Self.CodingKeys.self) try verifyTransactionVersion(container: container, codingKeysType: CodingKeys.self) } } @@ -268,8 +268,8 @@ public struct StarknetDeclareTransactionV0: StarknetTransaction { self.senderAddress = try container.decode(Felt.self, forKey: .senderAddress) self.hash = try container.decodeIfPresent(Felt.self, forKey: .hash) - try verifyTransactionType(container: container, codingKeysType: Self.CodingKeys) - try verifyTransactionVersion(container: container, codingKeysType: Self.CodingKeys) + try verifyTransactionType(container: container, codingKeysType: Self.CodingKeys.self) + try verifyTransactionVersion(container: container, codingKeysType: Self.CodingKeys.self) } } @@ -319,8 +319,8 @@ public struct StarknetDeclareTransactionV1: StarknetTransaction { self.senderAddress = try container.decode(Felt.self, forKey: .senderAddress) self.hash = try container.decodeIfPresent(Felt.self, forKey: .hash) - try verifyTransactionType(container: container, codingKeysType: Self.CodingKeys) - try verifyTransactionVersion(container: container, codingKeysType: Self.CodingKeys) + try verifyTransactionType(container: container, codingKeysType: Self.CodingKeys.self) + try verifyTransactionVersion(container: container, codingKeysType: Self.CodingKeys.self) } } @@ -375,8 +375,8 @@ public struct StarknetDeclareTransactionV2: StarknetTransaction { self.senderAddress = try container.decode(Felt.self, forKey: .senderAddress) self.hash = try container.decodeIfPresent(Felt.self, forKey: .hash) - try verifyTransactionType(container: container, codingKeysType: Self.CodingKeys) - try verifyTransactionVersion(container: container, codingKeysType: Self.CodingKeys) + try verifyTransactionType(container: container, codingKeysType: Self.CodingKeys.self) + try verifyTransactionVersion(container: container, codingKeysType: Self.CodingKeys.self) } } @@ -416,8 +416,8 @@ public struct StarknetDeployTransaction: StarknetTransaction { self.classHash = try container.decode(Felt.self, forKey: .classHash) self.hash = try container.decodeIfPresent(Felt.self, forKey: .hash) - try verifyTransactionType(container: container, codingKeysType: Self.CodingKeys) - try verifyTransactionVersion(container: container, codingKeysType: Self.CodingKeys) + try verifyTransactionType(container: container, codingKeysType: Self.CodingKeys.self) + try verifyTransactionVersion(container: container, codingKeysType: Self.CodingKeys.self) } } diff --git a/Sources/Starknet/Data/Transaction/TransactionStatus.swift b/Sources/Starknet/Data/Transaction/TransactionStatus.swift index 827205100..1d1aa5c9b 100644 --- a/Sources/Starknet/Data/Transaction/TransactionStatus.swift +++ b/Sources/Starknet/Data/Transaction/TransactionStatus.swift @@ -18,11 +18,15 @@ public enum StarknetTransactionFinalityStatus: String, Codable { } } -public enum LegacyStarknetTransactionStatus: String, Codable { +public enum StarknetGatewayTransactionStatus: String, Codable { case pending = "PENDING" case rejected = "REJECTED" case acceptedL1 = "ACCEPTED_ON_L1" case acceptedL2 = "ACCEPTED_ON_L2" + case received = "RECEIVED" + case notReceived = "NOT_RECEIVED" + case reverted = "REVERTED" + case aborted = "ABORTED" public var encodedValue: Felt { Felt.fromShortString(self.rawValue.lowercased())! diff --git a/Sources/Starknet/Providers/StarknetProvider/JsonRpcMethod.swift b/Sources/Starknet/Providers/StarknetProvider/JsonRpcMethod.swift index c101c66b4..022b5c14c 100644 --- a/Sources/Starknet/Providers/StarknetProvider/JsonRpcMethod.swift +++ b/Sources/Starknet/Providers/StarknetProvider/JsonRpcMethod.swift @@ -15,4 +15,5 @@ enum JsonRpcMethod: String, Encodable { case getTransactionReceipt = "starknet_getTransactionReceipt" case simulateTransactions = "starknet_simulateTransactions" case estimateMessageFee = "starknet_estimateMessageFee" + case pathfinderGetTransactionStatus = "pathfinder_getTransactionStatus" } diff --git a/Sources/Starknet/Providers/StarknetProvider/JsonRpcParams.swift b/Sources/Starknet/Providers/StarknetProvider/JsonRpcParams.swift index 201bd2c02..b14c769d3 100644 --- a/Sources/Starknet/Providers/StarknetProvider/JsonRpcParams.swift +++ b/Sources/Starknet/Providers/StarknetProvider/JsonRpcParams.swift @@ -118,6 +118,14 @@ struct GetTransactionReceiptPayload: Encodable { } } +struct GetTransactionStatusPayload: Encodable { + let transactionHash: Felt + + enum CodingKeys: String, CodingKey { + case transactionHash = "transaction_hash" + } +} + struct SimulateTransactionsParams: Encodable { let transactions: [any StarknetSequencerTransaction] let blockId: StarknetBlockId diff --git a/Sources/Starknet/Providers/StarknetProvider/StarknetProvider.swift b/Sources/Starknet/Providers/StarknetProvider/StarknetProvider.swift index 3ea6d3949..4141fb5fc 100644 --- a/Sources/Starknet/Providers/StarknetProvider/StarknetProvider.swift +++ b/Sources/Starknet/Providers/StarknetProvider/StarknetProvider.swift @@ -153,6 +153,15 @@ public class StarknetProvider: StarknetProviderProtocol { return result.transactionReceipt } + public func pathfinderGetTransactionStatus(hash: Felt) async throws -> StarknetGatewayTransactionStatus { + #warning("This method is currently supported only by Pathfinder nodes. It will be replaced by getTransactionStatus in starknet.swift 0.7.0") + let params = GetTransactionStatusPayload(transactionHash: hash) + + let result = try await makeRequest(method: .pathfinderGetTransactionStatus, params: params, receive: StarknetGatewayTransactionStatus.self) + + return result + } + public func simulateTransactions(_ transactions: [any StarknetSequencerTransaction], at blockId: StarknetBlockId, simulationFlags: Set) async throws -> [StarknetSimulatedTransaction] { let params = SimulateTransactionsParams(transactions: transactions, blockId: blockId, simulationFlags: simulationFlags) diff --git a/Sources/Starknet/Providers/StarknetProviderProtocol.swift b/Sources/Starknet/Providers/StarknetProviderProtocol.swift index 30db7ce2e..60b851c1f 100644 --- a/Sources/Starknet/Providers/StarknetProviderProtocol.swift +++ b/Sources/Starknet/Providers/StarknetProviderProtocol.swift @@ -97,13 +97,21 @@ public protocol StarknetProviderProtocol { /// - Returns: Transaction found with provided blockId and index. func getTransactionBy(blockId: StarknetBlockId, index: UInt64) async throws -> any StarknetTransaction - /// Get all event objects matching the conditions in the provided filter + /// Get transaction receipt of a submitted transaction /// /// - Parameters: - /// - txHash : the hash of the requested transaction + /// - hash : the hash of the requested transaction /// - Returns: receipt of a transaction identified by given hash func getTransactionReceiptBy(hash: Felt) async throws -> StarknetTransactionReceipt + /// Get the gateway status of a submitted transaction. + /// This method is supported only by Pathfinder nodes. + /// + /// - Parameters: + /// - hash: The hash of the requested transaction + /// - Returns: Transaction found with provided hash + func pathfinderGetTransactionStatus(hash: Felt) async throws -> StarknetGatewayTransactionStatus + /// Simulate running a given list of transactions, and generate the execution trace /// /// - Parameters: diff --git a/Tests/StarknetTests/Crypto/TransactionStatusTests.swift b/Tests/StarknetTests/Crypto/TransactionStatusTests.swift new file mode 100644 index 000000000..fb73fd425 --- /dev/null +++ b/Tests/StarknetTests/Crypto/TransactionStatusTests.swift @@ -0,0 +1,19 @@ +import XCTest + +@testable import Starknet + +final class TransactionStatusTests: XCTestCase { + func testGetTransactionStatusResponse() async throws { + let json = """ + {"jsonrpc":"2.0","result":"REJECTED","id":0} + """.data(using: .utf8)! + let invalidJson = """ + {"jsonrpc":"2.0","result":"INVALID_STATUS","id":0} + """.data(using: .utf8)! + + let decoder = JSONDecoder() + + XCTAssertNoThrow(try decoder.decode(JsonRpcResponse.self, from: json)) + XCTAssertThrowsError(try decoder.decode(JsonRpcResponse.self, from: invalidJson)) + } +} diff --git a/Tests/StarknetTests/Utils/DevnetClient/DevnetClientModels.swift b/Tests/StarknetTests/Utils/DevnetClient/DevnetClientModels.swift index 9b8a0ca27..c9f1bbef1 100644 --- a/Tests/StarknetTests/Utils/DevnetClient/DevnetClientModels.swift +++ b/Tests/StarknetTests/Utils/DevnetClient/DevnetClientModels.swift @@ -71,7 +71,7 @@ struct PrefundPayload: Codable { // to avoid DevnetClient relying on StarknetTransactionReceipt. // Only use it for checking whether a transaction was successful. struct DevnetReceipt: Decodable { - let status: LegacyStarknetTransactionStatus? + let status: StarknetGatewayTransactionStatus? let executionStatus: StarknetTransactionExecutionStatus? let finalityStatus: StarknetTransactionFinalityStatus? @@ -93,7 +93,7 @@ struct DevnetReceipt: Decodable { public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - self.status = try container.decodeIfPresent(LegacyStarknetTransactionStatus.self, forKey: .status) + self.status = try container.decodeIfPresent(StarknetGatewayTransactionStatus.self, forKey: .status) self.executionStatus = try container.decodeIfPresent(StarknetTransactionExecutionStatus.self, forKey: .executionStatus) self.finalityStatus = try container.decodeIfPresent(StarknetTransactionFinalityStatus.self, forKey: .finalityStatus)