diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 8dc43d265..7e82fd319 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -8,7 +8,7 @@ jobs: test_and_lint: runs-on: macos-12 env: - DEVNET_SHA: 55191ee549b33ccbb0bc9d20dd929e39832a5ea5 + DEVNET_SHA: fa1238e8039a53101b5d2d764d3622ff0403a527 steps: - uses: actions/checkout@v3 diff --git a/Sources/Starknet/Accounts/StarknetAccount.swift b/Sources/Starknet/Accounts/StarknetAccount.swift index f0d79bd08..7f03e2ef5 100644 --- a/Sources/Starknet/Accounts/StarknetAccount.swift +++ b/Sources/Starknet/Accounts/StarknetAccount.swift @@ -132,6 +132,28 @@ public class StarknetAccount: StarknetAccountProtocol { return try await provider.addInvokeTransaction(signedTransaction) } + public func executeV1(calls: [StarknetCall], estimateFeeMultiplier: Double) async throws -> StarknetInvokeTransactionResponse { + let nonce = try await getNonce() + let feeEstimate = try await estimateFeeV1(calls: calls, nonce: nonce) + let maxFee = feeEstimate.toMaxFee(multiplier: estimateFeeMultiplier) + + let params = StarknetInvokeParamsV1(nonce: nonce, maxFee: maxFee) + let signedTransaction = try signV1(calls: calls, params: params, forFeeEstimation: false) + + return try await provider.addInvokeTransaction(signedTransaction) + } + + public func executeV3(calls: [StarknetCall], estimateAmountMultiplier: Double, estimateUnitPriceMultiplier: Double) async throws -> StarknetInvokeTransactionResponse { + let nonce = try await getNonce() + let feeEstimate = try await estimateFeeV3(calls: calls, nonce: nonce) + let resourceBounds = feeEstimate.toResourceBounds(amountMultiplier: estimateAmountMultiplier, unitPriceMultiplier: estimateUnitPriceMultiplier) + + let params = StarknetInvokeParamsV3(nonce: nonce, l1ResourceBounds: resourceBounds.l1Gas) + let signedTransaction = try signV3(calls: calls, params: params, forFeeEstimation: false) + + return try await provider.addInvokeTransaction(signedTransaction) + } + public func estimateFeeV1(calls: [StarknetCall], nonce: Felt, skipValidate: Bool) async throws -> StarknetFeeEstimate { let params = StarknetInvokeParamsV1(nonce: nonce, maxFee: .zero) let signedTransaction = try signV1(calls: calls, params: params, forFeeEstimation: true) diff --git a/Sources/Starknet/Accounts/StarknetAccountProtocol.swift b/Sources/Starknet/Accounts/StarknetAccountProtocol.swift index 4b6a7b038..88fc0aa55 100644 --- a/Sources/Starknet/Accounts/StarknetAccountProtocol.swift +++ b/Sources/Starknet/Accounts/StarknetAccountProtocol.swift @@ -85,7 +85,26 @@ public protocol StarknetAccountProtocol { /// - Returns: InvokeTransactionResponse, containing transaction hash of submitted transaction. func executeV3(calls: [StarknetCall], params: StarknetOptionalInvokeParamsV3) async throws -> StarknetInvokeTransactionResponse - /// Execute list of calls as invoke transaction v1 + /// Execute list of calls as invoke transaction v1 with automatically estimated fee that will be multiplied by the specified multiplier when max fee is calculated. + /// + /// - Parameters: + /// - calls: list of calls to be executed. + /// - estimateFeeMultiplier: multiplier for the estimated fee. + /// + /// - Returns: InvokeTransactionResponse, containing transaction hash of submitted transaction. + func executeV1(calls: [StarknetCall], estimateFeeMultiplier: Double) async throws -> StarknetInvokeTransactionResponse + + /// Execute list of calls as invoke transaction v3 with automatically estimated fee that will be multiplied by the specified multipliers when resource bounds are calculated. + /// + /// - Parameters: + /// - calls: list of calls to be executed. + /// - estimateAmountMultiplier: multiplier for the estimated amount. + /// - estimateUnitPriceMultiplier: multiplier for the estimated unit price. + /// + /// - Returns: InvokeTransactionResponse, containing transaction hash of submitted transaction. + func executeV3(calls: [StarknetCall], estimateAmountMultiplier: Double, estimateUnitPriceMultiplier: Double) async throws -> StarknetInvokeTransactionResponse + + /// Execute list of calls as invoke transaction v1 with automatically estimated fee /// /// - Parameters: /// - calls: list of calls to be executed. @@ -93,7 +112,7 @@ public protocol StarknetAccountProtocol { /// - Returns: InvokeTransactionResponse, containing transaction hash of submitted transaction. func executeV1(calls: [StarknetCall]) async throws -> StarknetInvokeTransactionResponse - /// Execute list of calls as invoke transaction v3 + /// Execute list of calls as invoke transaction v3 with automatically estimated fee /// /// - Parameters: /// - calls: list of calls to be executed. @@ -269,7 +288,30 @@ public extension StarknetAccountProtocol { try await executeV3(calls: [call], params: params) } - /// Execute a call as invoke transaction v1 + /// Execute a call as invoke transaction v1 with automatically estimated fee that will be multiplied by the specified multiplier when max fee is calculated. + /// + /// - Parameters: + /// - call: a call to be executed. + /// - estimateFeeMultiplier: multiplier for the estimated fee. + /// + /// - Returns: InvokeTransactionResponse, containing transaction hash of submitted transaction. + func executeV1(call: StarknetCall, estimateFeeMultiplier: Double) async throws -> StarknetInvokeTransactionResponse { + try await executeV1(calls: [call], estimateFeeMultiplier: estimateFeeMultiplier) + } + + /// Execute a call as invoke transaction v3 with automatically estimated fee that will be multiplied by the specified multipliers when resource bounds are calculated. + /// + /// - Parameters: + /// - call: a call to be executed. + /// - estimateAmountMultiplier: multiplier for the estimated amount. + /// - estimateUnitPriceMultiplier: multiplier for the estimated unit price. + /// + /// - Returns: InvokeTransactionResponse, containing transaction hash of submitted transaction. + func executeV3(call: StarknetCall, estimateAmountMultiplier: Double, estimateUnitPriceMultiplier: Double) async throws -> StarknetInvokeTransactionResponse { + try await executeV3(calls: [call], estimateAmountMultiplier: estimateAmountMultiplier, estimateUnitPriceMultiplier: estimateUnitPriceMultiplier) + } + + /// Execute a call as invoke transaction v1 with automatically estimated fee /// /// - Parameters: /// - call: a call to be executed. @@ -279,7 +321,7 @@ public extension StarknetAccountProtocol { try await executeV1(calls: [call]) } - /// Execute a call as invoke transaction v3 + /// Execute a call as invoke transaction v3 with automatically estimated fee /// /// - Parameters: /// - call: a call to be executed. diff --git a/Sources/Starknet/Crypto/FeeCalculation.swift b/Sources/Starknet/Crypto/FeeCalculation.swift index 4a8fdd0a2..ae9beedf4 100644 --- a/Sources/Starknet/Crypto/FeeCalculation.swift +++ b/Sources/Starknet/Crypto/FeeCalculation.swift @@ -2,40 +2,43 @@ import BigInt import Foundation public extension StarknetFeeEstimate { - /// Convert estimated fee to resource bounds with added overhead + /// Convert estimated fee to resource bounds with applied multipliers /// - /// Add overhead to estimated fee. Calculates multiplier as m = round((1 + ovehead) \* 100%). - /// Then multiplies fee by m and does integer division by 100. + /// Calculates `maxAmount = overallFee / gasPrice`, unless `gasPrice` is 0, then `maxAmount` is 0. + /// Calculates `maxPricePerUnit = gasPrice`. + /// Then multiplies `maxAmount` by **round((amountMultiplier) \* 100)** and `maxPricePerUnit` by **round((unitPriceMultiplier) \* 100)** and performs integer division by 100 on both. /// /// - Parameters: - /// - amountOverhead: how big overhead should be added (as a fraction of amount) to the amount, defaults to 0.1 - /// - unitPriceOverhead: how big overhead should be added (as a fraction of unit price) to the unit price, defaults to 0.5 + /// - amountMultiplier: multiplier for max amount, defaults to 1.5. + /// - unitPriceMultiplier: multiplier for max price per unit, defaults to 1.5. /// - /// - Returns: resource bounds with added overhead - func toResourceBounds(amountOverhead: Double = 0.1, unitPriceOverhead: Double = 0.5) -> StarknetResourceBoundsMapping { - let maxAmount = addOverhead(self.gasConsumed.value, amountOverhead).toUInt64AsHexClamped() - let maxUnitPrice = addOverhead(self.gasPrice.value, unitPriceOverhead).toUInt128AsHexClamped() + /// - Returns: resource bounds with applied multipliers + func toResourceBounds(amountMultiplier: Double = 1.5, unitPriceMultiplier: Double = 1.5) -> StarknetResourceBoundsMapping { + let maxAmount = self.gasPrice == .zero ? UInt64AsHex.zero : (self.overallFee.value / self.gasPrice.value).applyMultiplier(amountMultiplier).toUInt64AsHexClamped() + + let maxUnitPrice = self.gasPrice.value.applyMultiplier(unitPriceMultiplier).toUInt128AsHexClamped() let l1Gas = StarknetResourceBounds(maxAmount: maxAmount, maxPricePerUnit: maxUnitPrice) return StarknetResourceBoundsMapping(l1Gas: l1Gas) } - /// Add overhead to estimated fee + /// Convert estimated fee to max fee with applied multiplier. /// - /// Add overhead to estimated fee. Calculates multiplier as m = round((1 + ovehead) \* 100%). - /// Then multiplies fee by m and does integer division by 100. + /// Multiplies `overallFee` by **round(multiplier \* 100)** and performs integer division by 100. /// /// - Parameters: - /// - overhead: how big overhead should be added (as a fraction of fee) to the fee, defaults to 0.1 + /// - multiplier: multiplier for estimated fee, defaults to 1.5. /// - /// - Returns: fee with added overhead - func toMaxFee(overhead: Double = 0.5) -> Felt { - addOverhead(self.overallFee.value, overhead).toFeltClamped() + /// - Returns: fee with applied multiplier + func toMaxFee(multiplier: Double = 1.5) -> Felt { + self.overallFee.value.applyMultiplier(multiplier).toFeltClamped() } } -private func addOverhead(_ value: BigUInt, _ overhead: Double) -> BigUInt { - let multiplier = BigUInt(Int((1.0 + overhead) * 100)) +private extension BigUInt { + func applyMultiplier(_ multiplier: Double) -> BigUInt { + let multiplier = BigUInt(Int(multiplier * 100)) - return value.multiplied(by: multiplier).quotientAndRemainder(dividingBy: 100).quotient + return self.multiplied(by: multiplier).quotientAndRemainder(dividingBy: 100).quotient + } } diff --git a/Sources/Starknet/Data/Responses.swift b/Sources/Starknet/Data/Responses.swift index 36a738f73..16ed6966c 100644 --- a/Sources/Starknet/Data/Responses.swift +++ b/Sources/Starknet/Data/Responses.swift @@ -11,12 +11,16 @@ public struct StarknetInvokeTransactionResponse: Decodable, Equatable { public struct StarknetFeeEstimate: Decodable, Equatable { public let gasConsumed: Felt public let gasPrice: Felt + public let dataGasConsumed: Felt + public let dataGasPrice: Felt public let overallFee: Felt public let feeUnit: StarknetPriceUnit enum CodingKeys: String, CodingKey { case gasConsumed = "gas_consumed" case gasPrice = "gas_price" + case dataGasConsumed = "data_gas_consumed" + case dataGasPrice = "data_gas_price" case overallFee = "overall_fee" case feeUnit = "unit" } diff --git a/Sources/Starknet/Data/Transaction/Data/ExecutionResources.swift b/Sources/Starknet/Data/Transaction/Data/ExecutionResources.swift index 067fce057..e9298b6f3 100644 --- a/Sources/Starknet/Data/Transaction/Data/ExecutionResources.swift +++ b/Sources/Starknet/Data/Transaction/Data/ExecutionResources.swift @@ -1,6 +1,45 @@ import Foundation -public struct StarknetExecutionResources: Decodable, Equatable { +public protocol StarknetResources: Decodable, Equatable { + var steps: Int { get } + var memoryHoles: Int? { get } + var rangeCheckApplications: Int? { get } + var pedersenApplications: Int? { get } + var poseidonApplications: Int? { get } + var ecOpApplications: Int? { get } + var ecdsaApplications: Int? { get } + var bitwiseApplications: Int? { get } + var keccakApplications: Int? { get } + var segmentArena: Int? { get } +} + +public struct StarknetComputationResources: StarknetResources { + public let steps: Int + public let memoryHoles: Int? + public let rangeCheckApplications: Int? + public let pedersenApplications: Int? + public let poseidonApplications: Int? + public let ecOpApplications: Int? + public let ecdsaApplications: Int? + public let bitwiseApplications: Int? + public let keccakApplications: Int? + public let segmentArena: Int? + + enum CodingKeys: String, CodingKey { + case steps + case memoryHoles = "memory_holes" + case rangeCheckApplications = "range_check_builtin_applications" + case pedersenApplications = "pedersen_builtin_applications" + case poseidonApplications = "poseidon_builtin_applications" + case ecOpApplications = "ec_op_builtin_applications" + case ecdsaApplications = "ecdsa_builtin_applications" + case bitwiseApplications = "bitwise_builtin_applications" + case keccakApplications = "keccak_builtin_applications" + case segmentArena = "segment_arena_builtin" + } +} + +public struct StarknetExecutionResources: StarknetResources { public let steps: Int public let memoryHoles: Int? public let rangeCheckApplications: Int? @@ -10,6 +49,8 @@ public struct StarknetExecutionResources: Decodable, Equatable { public let ecdsaApplications: Int? public let bitwiseApplications: Int? public let keccakApplications: Int? + public let segmentArena: Int? + public let dataAvailability: StarknetDataAvailability enum CodingKeys: String, CodingKey { case steps @@ -21,5 +62,17 @@ public struct StarknetExecutionResources: Decodable, Equatable { case ecdsaApplications = "ecdsa_builtin_applications" case bitwiseApplications = "bitwise_builtin_applications" case keccakApplications = "keccak_builtin_applications" + case segmentArena = "segment_arena_builtin" + case dataAvailability = "data_availability" + } +} + +public struct StarknetDataAvailability: Decodable, Equatable { + public let l1Gas: Int + public let l1DataGas: Int + + enum CodingKeys: String, CodingKey { + case l1Gas = "l1_gas" + case l1DataGas = "l1_data_gas" } } diff --git a/Sources/Starknet/Data/Transaction/Data/StarknetTransactionVersion.swift b/Sources/Starknet/Data/Transaction/Data/StarknetTransactionVersion.swift new file mode 100644 index 000000000..0002b37c5 --- /dev/null +++ b/Sources/Starknet/Data/Transaction/Data/StarknetTransactionVersion.swift @@ -0,0 +1,15 @@ +import Foundation + +public enum StarknetTransactionVersion: String, Codable { + case v0 = "0x0" + case v1 = "0x1" + case v1Query = "0x100000000000000000000000000000001" + case v2 = "0x2" + case v2Query = "0x100000000000000000000000000000002" + case v3 = "0x3" + case v3Query = "0x100000000000000000000000000000003" + + public var value: Felt { + Felt(fromHex: self.rawValue)! + } +} diff --git a/Sources/Starknet/Data/Transaction/Transaction.swift b/Sources/Starknet/Data/Transaction/Transaction.swift index 488840d5c..8e25b5cab 100644 --- a/Sources/Starknet/Data/Transaction/Transaction.swift +++ b/Sources/Starknet/Data/Transaction/Transaction.swift @@ -4,7 +4,7 @@ import Foundation public struct StarknetInvokeTransactionV3: StarknetInvokeTransaction, StarknetTransactionV3, StarknetExecutableTransaction { public let type: StarknetTransactionType = .invoke - public let version: Felt + public let version: StarknetTransactionVersion public let senderAddress: Felt @@ -33,7 +33,7 @@ public struct StarknetInvokeTransactionV3: StarknetInvokeTransaction, StarknetTr self.calldata = calldata self.signature = signature self.nonce = nonce - self.version = StarknetInvokeTransactionV3.computeVersion(3, forFeeEstimation: forFeeEstimation) + self.version = forFeeEstimation ? .v3Query : .v3 self.hash = hash // As of Starknet 0.13, most of v3 fields have hardcoded values. self.resourceBounds = StarknetResourceBoundsMapping(l1Gas: l1ResourceBounds) @@ -66,7 +66,7 @@ public struct StarknetInvokeTransactionV3: StarknetInvokeTransaction, StarknetTr self.calldata = try container.decode(StarknetCalldata.self, forKey: .calldata) self.signature = try container.decode(StarknetSignature.self, forKey: .signature) self.nonce = try container.decode(Felt.self, forKey: .nonce) - self.version = try container.decode(Felt.self, forKey: .version) + self.version = try container.decode(StarknetTransactionVersion.self, forKey: .version) self.resourceBounds = try container.decode(StarknetResourceBoundsMapping.self, forKey: .resourceBounds) self.tip = try container.decode(UInt64AsHex.self, forKey: .tip) self.paymasterData = try container.decode(StarknetPaymasterData.self, forKey: .paymasterData) @@ -82,7 +82,7 @@ public struct StarknetInvokeTransactionV3: StarknetInvokeTransaction, StarknetTr public struct StarknetInvokeTransactionV1: StarknetInvokeTransaction, StarknetDeprecatedTransaction, StarknetExecutableTransaction { public let type: StarknetTransactionType = .invoke - public let version: Felt + public let version: StarknetTransactionVersion public let senderAddress: Felt @@ -102,7 +102,7 @@ public struct StarknetInvokeTransactionV1: StarknetInvokeTransaction, StarknetDe self.signature = signature self.maxFee = maxFee self.nonce = nonce - self.version = StarknetInvokeTransactionV1.computeVersion(1, forFeeEstimation: forFeeEstimation) + self.version = forFeeEstimation ? .v1Query : .v1 self.hash = hash } @@ -124,7 +124,7 @@ public struct StarknetInvokeTransactionV1: StarknetInvokeTransaction, StarknetDe self.signature = try container.decode(StarknetSignature.self, forKey: .signature) self.maxFee = try container.decode(Felt.self, forKey: .maxFee) self.nonce = try container.decode(Felt.self, forKey: .nonce) - self.version = try container.decode(Felt.self, forKey: .version) + self.version = try container.decode(StarknetTransactionVersion.self, forKey: .version) self.hash = try container.decodeIfPresent(Felt.self, forKey: .hash) try verifyTransactionType(container: container, codingKeysType: CodingKeys.self) @@ -134,7 +134,7 @@ public struct StarknetInvokeTransactionV1: StarknetInvokeTransaction, StarknetDe public struct StarknetInvokeTransactionV0: StarknetInvokeTransaction, StarknetDeprecatedTransaction { public let type: StarknetTransactionType = .invoke - public let version: Felt = .zero + public let version: StarknetTransactionVersion = .v0 public let contractAddress: Felt @@ -185,7 +185,7 @@ public struct StarknetInvokeTransactionV0: StarknetInvokeTransaction, StarknetDe public struct StarknetDeployAccountTransactionV3: StarknetDeployAccountTransaction, StarknetTransactionV3, StarknetExecutableTransaction { public let type: StarknetTransactionType = .deployAccount - public let version: Felt + public let version: StarknetTransactionVersion public let signature: StarknetSignature @@ -215,7 +215,7 @@ public struct StarknetDeployAccountTransactionV3: StarknetDeployAccountTransacti self.contractAddressSalt = contractAddressSalt self.constructorCalldata = constructorCalldata self.classHash = classHash - self.version = StarknetDeployAccountTransactionV3.computeVersion(3, forFeeEstimation: forFeeEstimation) + self.version = forFeeEstimation ? .v3Query : .v3 self.hash = hash // As of Starknet 0.13, most of v3 fields have hardcoded values. self.resourceBounds = StarknetResourceBoundsMapping(l1Gas: l1ResourceBounds) @@ -237,7 +237,7 @@ public struct StarknetDeployAccountTransactionV3: StarknetDeployAccountTransacti self.paymasterData = try container.decode([Felt].self, forKey: .paymasterData) self.nonceDataAvailabilityMode = try container.decode(StarknetDAMode.self, forKey: .nonceDataAvailabilityMode) self.feeDataAvailabilityMode = try container.decode(StarknetDAMode.self, forKey: .feeDataAvailabilityMode) - self.version = try container.decode(Felt.self, forKey: .version) + self.version = try container.decode(StarknetTransactionVersion.self, forKey: .version) self.hash = try container.decodeIfPresent(Felt.self, forKey: .hash) try verifyTransactionVersion(container: container, codingKeysType: CodingKeys.self) @@ -263,7 +263,7 @@ public struct StarknetDeployAccountTransactionV3: StarknetDeployAccountTransacti public struct StarknetDeployAccountTransactionV1: StarknetDeployAccountTransaction, StarknetDeprecatedTransaction, StarknetExecutableTransaction { public let type: StarknetTransactionType = .deployAccount - public let version: Felt + public let version: StarknetTransactionVersion public let signature: StarknetSignature @@ -286,7 +286,7 @@ public struct StarknetDeployAccountTransactionV1: StarknetDeployAccountTransacti self.contractAddressSalt = contractAddressSalt self.constructorCalldata = constructorCalldata self.classHash = classHash - self.version = StarknetDeployAccountTransactionV1.computeVersion(1, forFeeEstimation: forFeeEstimation) + self.version = forFeeEstimation ? .v1Query : .v1 self.hash = hash } @@ -298,7 +298,7 @@ public struct StarknetDeployAccountTransactionV1: StarknetDeployAccountTransacti self.contractAddressSalt = try container.decode(Felt.self, forKey: .contractAddressSalt) self.constructorCalldata = try container.decode(StarknetCalldata.self, forKey: .constructorCalldata) self.classHash = try container.decode(Felt.self, forKey: .classHash) - self.version = try container.decode(Felt.self, forKey: .version) + self.version = try container.decode(StarknetTransactionVersion.self, forKey: .version) self.hash = try container.decodeIfPresent(Felt.self, forKey: .hash) try verifyTransactionType(container: container, codingKeysType: CodingKeys.self) @@ -320,7 +320,7 @@ public struct StarknetDeployAccountTransactionV1: StarknetDeployAccountTransacti public struct StarknetL1HandlerTransaction: StarknetTransaction { public let type: StarknetTransactionType = .l1Handler - public let version: Felt = .zero + public let version: StarknetTransactionVersion = .v0 public let nonce: Felt @@ -366,7 +366,7 @@ public struct StarknetL1HandlerTransaction: StarknetTransaction { public struct StarknetDeclareTransactionV3: StarknetDeclareTransaction, StarknetTransactionV3 { public let type: StarknetTransactionType = .declare - public let version: Felt = 3 + public let version: StarknetTransactionVersion = .v3 public let signature: StarknetSignature @@ -452,7 +452,7 @@ public struct StarknetDeclareTransactionV0: StarknetDeclareTransaction, Starknet public let maxFee: Felt - public let version: Felt = .zero + public let version: StarknetTransactionVersion = .v0 public let signature: StarknetSignature @@ -498,7 +498,7 @@ public struct StarknetDeclareTransactionV1: StarknetDeclareTransaction, Starknet public let maxFee: Felt - public let version: Felt = .one + public let version: StarknetTransactionVersion = .v1 public let signature: StarknetSignature @@ -549,7 +549,7 @@ public struct StarknetDeclareTransactionV2: StarknetTransaction { public let maxFee: Felt - public let version: Felt = 2 + public let version: StarknetTransactionVersion = .v2 public let signature: StarknetSignature @@ -603,7 +603,7 @@ public struct StarknetDeclareTransactionV2: StarknetTransaction { public struct StarknetDeployTransaction: StarknetTransaction { public let type: StarknetTransactionType = .deploy - public let version: Felt = .zero + public let version: StarknetTransactionVersion = .v0 public let contractAddressSalt: Felt @@ -650,10 +650,6 @@ extension StarknetExecutableTransaction { private static func estimateVersion(_ version: Felt) -> Felt { Felt(BigUInt(2).power(128).advanced(by: BigInt(version.value)))! } - - static func computeVersion(_ version: Felt, forFeeEstimation: Bool) -> Felt { - forFeeEstimation ? estimateVersion(version) : version - } } // Default deserializer doesn't check if the fields with default values match what is deserialized. @@ -668,7 +664,7 @@ extension StarknetTransaction { } func verifyTransactionVersion(container: KeyedDecodingContainer, codingKeysType _: T.Type) throws where T: CodingKey { - let version = try container.decode(Felt.self, forKey: T(stringValue: "version")!) + let version = try container.decode(StarknetTransactionVersion.self, forKey: T(stringValue: "version")!) guard version == self.version else { throw StarknetTransactionDecodingError.invalidVersion diff --git a/Sources/Starknet/Data/Transaction/TransactionHash.swift b/Sources/Starknet/Data/Transaction/TransactionHash.swift index 2286a82eb..a31f67bac 100644 --- a/Sources/Starknet/Data/Transaction/TransactionHash.swift +++ b/Sources/Starknet/Data/Transaction/TransactionHash.swift @@ -6,7 +6,7 @@ public class StarknetTransactionHashCalculator { private class func computeCommonDeprecatedTransactionHash( transactionType: StarknetTransactionType, - version: Felt, + version: StarknetTransactionVersion, contractAddress: Felt, entryPointSelector: Felt, calldata: StarknetCalldata, @@ -16,7 +16,7 @@ public class StarknetTransactionHashCalculator { ) -> Felt { StarknetCurve.pedersenOn( transactionType.encodedValue, - version, + version.value, contractAddress, entryPointSelector, StarknetCurve.pedersenOn(calldata), @@ -38,7 +38,7 @@ public class StarknetTransactionHashCalculator { return [ transactionType.encodedValue, - version, + version.value, address, StarknetPoseidon.poseidonHash( [tip.value.toFelt()!] diff --git a/Sources/Starknet/Data/Transaction/TransactionProtocol.swift b/Sources/Starknet/Data/Transaction/TransactionProtocol.swift index 04ad12c0c..2c5db5cfe 100644 --- a/Sources/Starknet/Data/Transaction/TransactionProtocol.swift +++ b/Sources/Starknet/Data/Transaction/TransactionProtocol.swift @@ -35,6 +35,6 @@ public protocol StarknetExecutableTransaction: StarknetTransaction {} public protocol StarknetTransaction: Codable, Hashable, Equatable { var type: StarknetTransactionType { get } - var version: Felt { get } + var version: StarknetTransactionVersion { get } var hash: Felt? { get } } diff --git a/Sources/Starknet/Data/Transaction/TransactionReceipt.swift b/Sources/Starknet/Data/Transaction/TransactionReceipt.swift index ef3b2a245..be9d219b9 100644 --- a/Sources/Starknet/Data/Transaction/TransactionReceipt.swift +++ b/Sources/Starknet/Data/Transaction/TransactionReceipt.swift @@ -1,10 +1,10 @@ import Foundation -public struct StarknetProcessedInvokeTransactionReceipt: StarknetProcessedTransactionReceipt, StarknetInvokeTransactionReceipt { +public struct StarknetInvokeTransactionReceipt: StarknetInvokeTransactionReceiptProtocol { public let transactionHash: Felt public let actualFee: StarknetFeePayment - public let blockHash: Felt - public let blockNumber: UInt64 + public let blockHash: Felt? + public let blockNumber: UInt64? public let messagesSent: [StarknetMessageToL1] public let events: [StarknetEvent] public let revertReason: String? @@ -31,38 +31,11 @@ public struct StarknetProcessedInvokeTransactionReceipt: StarknetProcessedTransa } } -public struct StarknetPendingInvokeTransactionReceipt: StarknetPendingTransactionReceipt, StarknetInvokeTransactionReceipt { +public struct StarknetDeclareTransactionReceipt: StarknetDeclareTransactionReceiptProtocol { public let transactionHash: Felt public let actualFee: StarknetFeePayment - public let messagesSent: [StarknetMessageToL1] - public let events: [StarknetEvent] - public let executionStatus: StarknetTransactionExecutionStatus - public let finalityStatus: StarknetTransactionFinalityStatus - public var executionResources: StarknetExecutionResources - public let revertReason: String? - public let type: StarknetTransactionType = .invoke - - public var isSuccessful: Bool { - executionStatus == .succeeded && (finalityStatus == .acceptedL1 || finalityStatus == .acceptedL2) - } - - enum CodingKeys: String, CodingKey { - case transactionHash = "transaction_hash" - case actualFee = "actual_fee" - case messagesSent = "messages_sent" - case events - case finalityStatus = "finality_status" - case executionStatus = "execution_status" - case executionResources = "execution_resources" - case revertReason = "revert_reason" - } -} - -public struct StarknetProcessedDeclareTransactionReceipt: StarknetProcessedTransactionReceipt, StarknetDeclareTransactionReceipt { - public let transactionHash: Felt - public let actualFee: StarknetFeePayment - public let blockHash: Felt - public let blockNumber: UInt64 + public let blockHash: Felt? + public let blockNumber: UInt64? public let messagesSent: [StarknetMessageToL1] public let events: [StarknetEvent] public let revertReason: String? @@ -89,38 +62,11 @@ public struct StarknetProcessedDeclareTransactionReceipt: StarknetProcessedTrans } } -public struct StarknetPendingDeclareTransactionReceipt: StarknetPendingTransactionReceipt, StarknetDeclareTransactionReceipt { - public let transactionHash: Felt - public let actualFee: StarknetFeePayment - public let messagesSent: [StarknetMessageToL1] - public let events: [StarknetEvent] - public let executionStatus: StarknetTransactionExecutionStatus - public let finalityStatus: StarknetTransactionFinalityStatus - public var executionResources: StarknetExecutionResources - public let revertReason: String? - public let type: StarknetTransactionType = .declare - - public var isSuccessful: Bool { - executionStatus == .succeeded && (finalityStatus == .acceptedL1 || finalityStatus == .acceptedL2) - } - - enum CodingKeys: String, CodingKey { - case transactionHash = "transaction_hash" - case actualFee = "actual_fee" - case messagesSent = "messages_sent" - case events - case finalityStatus = "finality_status" - case executionStatus = "execution_status" - case executionResources = "execution_resources" - case revertReason = "revert_reason" - } -} - -public struct StarknetProcessedDeployAccountTransactionReceipt: StarknetProcessedTransactionReceipt, StarknetDeployAccountTransactionReceipt { +public struct StarknetDeployAccountTransactionReceipt: StarknetDeployAccountTransactionReceiptProtocol { public let transactionHash: Felt public let actualFee: StarknetFeePayment - public let blockHash: Felt - public let blockNumber: UInt64 + public let blockHash: Felt? + public let blockNumber: UInt64? public let messagesSent: [StarknetMessageToL1] public let events: [StarknetEvent] public let revertReason: String? @@ -149,40 +95,11 @@ public struct StarknetProcessedDeployAccountTransactionReceipt: StarknetProcesse } } -public struct StarknetPendingDeployAccountTransactionReceipt: StarknetPendingTransactionReceipt, StarknetDeployAccountTransactionReceipt { - public let transactionHash: Felt - public let actualFee: StarknetFeePayment - public let messagesSent: [StarknetMessageToL1] - public let events: [StarknetEvent] - public let executionStatus: StarknetTransactionExecutionStatus - public let finalityStatus: StarknetTransactionFinalityStatus - public var executionResources: StarknetExecutionResources - public let revertReason: String? - public let contractAddress: Felt - public let type: StarknetTransactionType = .deployAccount - - public var isSuccessful: Bool { - executionStatus == .succeeded && (finalityStatus == .acceptedL1 || finalityStatus == .acceptedL2) - } - - enum CodingKeys: String, CodingKey { - case transactionHash = "transaction_hash" - case actualFee = "actual_fee" - case messagesSent = "messages_sent" - case events - case finalityStatus = "finality_status" - case executionStatus = "execution_status" - case executionResources = "execution_resources" - case revertReason = "revert_reason" - case contractAddress = "contract_address" - } -} - -public struct StarknetProcessedDeployTransactionReceipt: StarknetProcessedTransactionReceipt, StarknetDeployTransactionReceipt { +public struct StarknetDeployTransactionReceipt: StarknetDeployTransactionReceiptProtocol { public let transactionHash: Felt public let actualFee: StarknetFeePayment - public let blockHash: Felt - public let blockNumber: UInt64 + public let blockHash: Felt? + public let blockNumber: UInt64? public let messagesSent: [StarknetMessageToL1] public let events: [StarknetEvent] public let revertReason: String? @@ -211,11 +128,11 @@ public struct StarknetProcessedDeployTransactionReceipt: StarknetProcessedTransa } } -public struct StarknetProcessedL1HandlerTransactionReceipt: StarknetProcessedTransactionReceipt, StarknetL1HandlerTransactionReceipt { +public struct StarknetL1HandlerTransactionReceipt: StarknetL1HandlerTransactionReceiptProtocol { public let transactionHash: Felt public let actualFee: StarknetFeePayment - public let blockHash: Felt - public let blockNumber: UInt64 + public let blockHash: Felt? + public let blockNumber: UInt64? public let messagesSent: [StarknetMessageToL1] public let events: [StarknetEvent] public let revertReason: String? @@ -243,32 +160,3 @@ public struct StarknetProcessedL1HandlerTransactionReceipt: StarknetProcessedTra case messageHash = "message_hash" } } - -public struct StarknetPendingL1HandlerTransactionReceipt: StarknetPendingTransactionReceipt, StarknetL1HandlerTransactionReceipt { - public let transactionHash: Felt - public let actualFee: StarknetFeePayment - public let messagesSent: [StarknetMessageToL1] - public let events: [StarknetEvent] - public let executionStatus: StarknetTransactionExecutionStatus - public let finalityStatus: StarknetTransactionFinalityStatus - public var executionResources: StarknetExecutionResources - public let revertReason: String? - public let messageHash: NumAsHex - public let type: StarknetTransactionType = .l1Handler - - public var isSuccessful: Bool { - executionStatus == .succeeded && (finalityStatus == .acceptedL1 || finalityStatus == .acceptedL2) - } - - enum CodingKeys: String, CodingKey { - case transactionHash = "transaction_hash" - case actualFee = "actual_fee" - case messagesSent = "messages_sent" - case events - case finalityStatus = "finality_status" - case executionStatus = "execution_status" - case executionResources = "execution_resources" - case revertReason = "revert_reason" - case messageHash = "message_hash" - } -} diff --git a/Sources/Starknet/Data/Transaction/TransactionReceiptProtocol.swift b/Sources/Starknet/Data/Transaction/TransactionReceiptProtocol.swift index 5c8dc5a11..48678960b 100644 --- a/Sources/Starknet/Data/Transaction/TransactionReceiptProtocol.swift +++ b/Sources/Starknet/Data/Transaction/TransactionReceiptProtocol.swift @@ -1,28 +1,21 @@ import Foundation -public protocol StarknetInvokeTransactionReceipt: StarknetTransactionReceipt {} +public protocol StarknetInvokeTransactionReceiptProtocol: StarknetTransactionReceipt {} -public protocol StarknetDeclareTransactionReceipt: StarknetTransactionReceipt {} +public protocol StarknetDeclareTransactionReceiptProtocol: StarknetTransactionReceipt {} -public protocol StarknetDeployTransactionReceipt: StarknetTransactionReceipt { +public protocol StarknetDeployTransactionReceiptProtocol: StarknetTransactionReceipt { var contractAddress: Felt { get } } -public protocol StarknetDeployAccountTransactionReceipt: StarknetTransactionReceipt { +public protocol StarknetDeployAccountTransactionReceiptProtocol: StarknetTransactionReceipt { var contractAddress: Felt { get } } -public protocol StarknetL1HandlerTransactionReceipt: StarknetTransactionReceipt { +public protocol StarknetL1HandlerTransactionReceiptProtocol: StarknetTransactionReceipt { var messageHash: NumAsHex { get } } -public protocol StarknetProcessedTransactionReceipt: StarknetTransactionReceipt { - var blockHash: Felt { get } - var blockNumber: UInt64 { get } -} - -public protocol StarknetPendingTransactionReceipt: StarknetTransactionReceipt {} - public protocol StarknetTransactionReceipt: Decodable, Equatable { var transactionHash: Felt { get } var actualFee: StarknetFeePayment { get } @@ -33,6 +26,9 @@ public protocol StarknetTransactionReceipt: Decodable, Equatable { var executionResources: StarknetExecutionResources { get } var revertReason: String? { get } var type: StarknetTransactionType { get } + // Block info + var blockHash: Felt? { get } + var blockNumber: UInt64? { get } var isSuccessful: Bool { get } } diff --git a/Sources/Starknet/Data/Transaction/TransactionReceiptWrapper.swift b/Sources/Starknet/Data/Transaction/TransactionReceiptWrapper.swift index 399f780fe..8d627a5cd 100644 --- a/Sources/Starknet/Data/Transaction/TransactionReceiptWrapper.swift +++ b/Sources/Starknet/Data/Transaction/TransactionReceiptWrapper.swift @@ -2,20 +2,14 @@ import Foundation enum TransactionReceiptWrapper: Decodable { fileprivate enum Keys: String, CodingKey { - case blockHash = "block_hash" - case blockNumber = "block_number" case type } - case invoke(StarknetProcessedInvokeTransactionReceipt) - case declare(StarknetProcessedDeclareTransactionReceipt) - case deployAccount(StarknetProcessedDeployAccountTransactionReceipt) - case l1Handler(StarknetProcessedL1HandlerTransactionReceipt) - case deploy(StarknetProcessedDeployTransactionReceipt) - case pendingInvoke(StarknetPendingInvokeTransactionReceipt) - case pendingDeclare(StarknetPendingDeclareTransactionReceipt) - case pendingDeployAccount(StarknetPendingDeployAccountTransactionReceipt) - case pendingL1Handler(StarknetPendingL1HandlerTransactionReceipt) + case invoke(StarknetInvokeTransactionReceipt) + case declare(StarknetDeclareTransactionReceipt) + case deployAccount(StarknetDeployAccountTransactionReceipt) + case l1Handler(StarknetL1HandlerTransactionReceipt) + case deploy(StarknetDeployTransactionReceipt) public var transactionReceipt: any StarknetTransactionReceipt { switch self { @@ -29,14 +23,6 @@ enum TransactionReceiptWrapper: Decodable { return tx case let .deploy(tx): return tx - case let .pendingInvoke(tx): - return tx - case let .pendingDeclare(tx): - return tx - case let .pendingDeployAccount(tx): - return tx - case let .pendingL1Handler(tx): - return tx } } @@ -44,32 +30,18 @@ enum TransactionReceiptWrapper: Decodable { let container = try decoder.container(keyedBy: Keys.self) let type = try container.decode(StarknetTransactionType.self, forKey: Keys.type) - let blockHash = try container.decodeIfPresent(Felt.self, forKey: Keys.blockHash) - let blockNumber = try container.decodeIfPresent(Felt.self, forKey: Keys.blockHash) - - let isPending = blockHash == nil || blockNumber == nil - switch (type, isPending) { - case (.invoke, false): - self = try .invoke(StarknetProcessedInvokeTransactionReceipt(from: decoder)) - case (.declare, false): - self = try .declare(StarknetProcessedDeclareTransactionReceipt(from: decoder)) - case (.deployAccount, false): - self = try .deployAccount(StarknetProcessedDeployAccountTransactionReceipt(from: decoder)) - case (.l1Handler, false): - self = try .l1Handler(StarknetProcessedL1HandlerTransactionReceipt(from: decoder)) - case (.deploy, false): - self = try .deploy(StarknetProcessedDeployTransactionReceipt(from: decoder)) - case (.invoke, true): - self = try .pendingInvoke(StarknetPendingInvokeTransactionReceipt(from: decoder)) - case (.declare, true): - self = try .pendingDeclare(StarknetPendingDeclareTransactionReceipt(from: decoder)) - case (.deployAccount, true): - self = try .pendingDeployAccount(StarknetPendingDeployAccountTransactionReceipt(from: decoder)) - case (.l1Handler, true): - self = try .pendingL1Handler(StarknetPendingL1HandlerTransactionReceipt(from: decoder)) - default: - throw DecodingError.dataCorruptedError(forKey: Keys.type, in: container, debugDescription: "Invalid transaction receipt type (\(isPending ? "pending" : "") \(type))") + switch type { + case .invoke: + self = try .invoke(StarknetInvokeTransactionReceipt(from: decoder)) + case .deployAccount: + self = try .deployAccount(StarknetDeployAccountTransactionReceipt(from: decoder)) + case .declare: + self = try .declare(StarknetDeclareTransactionReceipt(from: decoder)) + case .l1Handler: + self = try .l1Handler(StarknetL1HandlerTransactionReceipt(from: decoder)) + case .deploy: + self = try .deploy(StarknetDeployTransactionReceipt(from: decoder)) } } } diff --git a/Sources/Starknet/Data/Transaction/TransactionTrace.swift b/Sources/Starknet/Data/Transaction/TransactionTrace.swift index 00b72b24f..78854161e 100644 --- a/Sources/Starknet/Data/Transaction/TransactionTrace.swift +++ b/Sources/Starknet/Data/Transaction/TransactionTrace.swift @@ -33,6 +33,7 @@ public struct StarknetFunctionInvocation: Decodable, Equatable { public let calls: [StarknetFunctionInvocation] public let events: [StarknetOrderedEvent] public let messages: [StarknetOrderedMessageToL1] + public let computationResources: StarknetComputationResources private enum CodingKeys: String, CodingKey { case contractAddress = "contract_address" @@ -46,6 +47,7 @@ public struct StarknetFunctionInvocation: Decodable, Equatable { case calls case events case messages + case computationResources = "execution_resources" } } @@ -66,6 +68,7 @@ public protocol StarknetInvokeTransactionTraceProtocol: StarknetTransactionTrace var validateInvocation: StarknetFunctionInvocation? { get } var feeTransferInvocation: StarknetFunctionInvocation? { get } var stateDiff: StarknetStateDiff? { get } + var executionResources: StarknetExecutionResources { get } var type: StarknetTransactionType { get } } @@ -74,6 +77,7 @@ public struct StarknetInvokeTransactionTrace: StarknetInvokeTransactionTraceProt public let executeInvocation: StarknetFunctionInvocation public let feeTransferInvocation: StarknetFunctionInvocation? public let stateDiff: StarknetStateDiff? + public let executionResources: StarknetExecutionResources public let type: StarknetTransactionType = .invoke private enum CodingKeys: String, CodingKey { @@ -81,6 +85,7 @@ public struct StarknetInvokeTransactionTrace: StarknetInvokeTransactionTraceProt case executeInvocation = "execute_invocation" case feeTransferInvocation = "fee_transfer_invocation" case stateDiff = "state_diff" + case executionResources = "execution_resources" } } @@ -89,6 +94,7 @@ public struct StarknetRevertedInvokeTransactionTrace: StarknetInvokeTransactionT public let executeInvocation: StarknetRevertedFunctionInvocation public let feeTransferInvocation: StarknetFunctionInvocation? public let stateDiff: StarknetStateDiff? + public let executionResources: StarknetExecutionResources public let type: StarknetTransactionType = .invoke private enum CodingKeys: String, CodingKey { @@ -96,6 +102,7 @@ public struct StarknetRevertedInvokeTransactionTrace: StarknetInvokeTransactionT case executeInvocation = "execute_invocation" case feeTransferInvocation = "fee_transfer_invocation" case stateDiff = "state_diff" + case executionResources = "execution_resources" } } @@ -104,6 +111,7 @@ public struct StarknetDeployAccountTransactionTrace: StarknetTransactionTrace { public let constructorInvocation: StarknetFunctionInvocation public let feeTransferInvocation: StarknetFunctionInvocation? public let stateDiff: StarknetStateDiff? + public let executionResources: StarknetExecutionResources public let type: StarknetTransactionType = .deployAccount private enum CodingKeys: String, CodingKey { @@ -111,17 +119,20 @@ public struct StarknetDeployAccountTransactionTrace: StarknetTransactionTrace { case constructorInvocation = "constructor_invocation" case feeTransferInvocation = "fee_transfer_invocation" case stateDiff = "state_diff" + case executionResources = "execution_resources" } } public struct StarknetL1HandlerTransactionTrace: StarknetTransactionTrace { public let functionInvocation: StarknetFunctionInvocation public let stateDiff: StarknetStateDiff? + public let executionResources: StarknetExecutionResources? public let type: StarknetTransactionType = .l1Handler private enum CodingKeys: String, CodingKey { case functionInvocation = "function_invocation" case stateDiff = "state_diff" + case executionResources = "execution_resources" } } diff --git a/Sources/Starknet/Data/Transaction/TransactionWrapper.swift b/Sources/Starknet/Data/Transaction/TransactionWrapper.swift index 6e12031b4..ea582574a 100644 --- a/Sources/Starknet/Data/Transaction/TransactionWrapper.swift +++ b/Sources/Starknet/Data/Transaction/TransactionWrapper.swift @@ -7,9 +7,9 @@ enum TransactionWrapper: Decodable { case version } + case invokeV3(StarknetInvokeTransactionV3) case invokeV1(StarknetInvokeTransactionV1) case invokeV0(StarknetInvokeTransactionV0) - case invokeV3(StarknetInvokeTransactionV3) case deployAccountV3(StarknetDeployAccountTransactionV3) case deployAccountV1(StarknetDeployAccountTransactionV1) case deploy(StarknetDeployTransaction) @@ -49,30 +49,30 @@ enum TransactionWrapper: Decodable { public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: Keys.self) let type = try container.decode(StarknetTransactionType.self, forKey: Keys.type) - let version = try container.decode(Felt.self, forKey: Keys.version) + let version = try container.decode(StarknetTransactionVersion.self, forKey: Keys.version) switch (type, version) { - case (.invoke, 3): + case (.invoke, .v3): self = try .invokeV3(StarknetInvokeTransactionV3(from: decoder)) - case (.invoke, .one): + case (.invoke, .v1): self = try .invokeV1(StarknetInvokeTransactionV1(from: decoder)) - case (.invoke, .zero): + case (.invoke, .v0): self = try .invokeV0(StarknetInvokeTransactionV0(from: decoder)) - case (.deployAccount, 3): + case (.deployAccount, .v3): self = try .deployAccountV3(StarknetDeployAccountTransactionV3(from: decoder)) - case (.deployAccount, .one): + case (.deployAccount, .v1): self = try .deployAccountV1(StarknetDeployAccountTransactionV1(from: decoder)) - case (.declare, 3): + case (.declare, .v3): self = try .declareV3(StarknetDeclareTransactionV3(from: decoder)) - case (.declare, 2): + case (.declare, .v2): self = try .declareV2(StarknetDeclareTransactionV2(from: decoder)) - case (.declare, .one): + case (.declare, .v1): self = try .declareV1(StarknetDeclareTransactionV1(from: decoder)) - case (.declare, .zero): + case (.declare, .v0): self = try .declareV0(StarknetDeclareTransactionV0(from: decoder)) - case (.deploy, .zero): + case (.deploy, .v0): self = try .deploy(StarknetDeployTransaction(from: decoder)) - case (.l1Handler, .zero): + case (.l1Handler, .v0): self = try .l1Handler(StarknetL1HandlerTransaction(from: decoder)) default: throw DecodingError.dataCorruptedError(forKey: Keys.version, in: container, debugDescription: "Invalid transaction version (\(version) for transaction type (\(type))") diff --git a/Tests/StarknetTests/Accounts/AccountTest.swift b/Tests/StarknetTests/Accounts/AccountTest.swift index e1af0af49..7e833d254 100644 --- a/Tests/StarknetTests/Accounts/AccountTest.swift +++ b/Tests/StarknetTests/Accounts/AccountTest.swift @@ -25,7 +25,7 @@ final class AccountTests: XCTestCase { let accountDetails = Self.devnetClient.constants.predeployedAccount1 signer = StarkCurveSigner(privateKey: accountDetails.privateKey)! chainId = try await provider.getChainId() - account = StarknetAccount(address: accountDetails.address, signer: signer, provider: provider, chainId: chainId, cairoVersion: .zero) + account = StarknetAccount(address: accountDetails.address, signer: signer, provider: provider, chainId: chainId, cairoVersion: .one) } override class func setUp() { @@ -45,7 +45,7 @@ final class AccountTests: XCTestCase { let _ = try await account.getNonce() } - func testExecute() async throws { + func testExecuteV1() async throws { let recipientAddress = AccountTests.devnetClient.constants.predeployedAccount2.address let calldata: [Felt] = [ @@ -77,7 +77,33 @@ final class AccountTests: XCTestCase { try await Self.devnetClient.assertTransactionSucceeded(transactionHash: result.transactionHash) } - func testExecuteCustomParams() async throws { + func testExecuteV1FeeMultiplier() async throws { + let recipientAddress = AccountTests.devnetClient.constants.predeployedAccount2.address + + let calldata: [Felt] = [recipientAddress, 1000, 0] + let call = StarknetCall(contractAddress: ethContractAddress, entrypoint: starknetSelector(from: "transfer"), calldata: calldata) + + let result = try await account.executeV1(call: call, estimateFeeMultiplier: 1.8) + try await Self.devnetClient.assertTransactionSucceeded(transactionHash: result.transactionHash) + + let result2 = try await account.executeV1(call: call, estimateFeeMultiplier: 0.9) + try await Self.devnetClient.assertTransactionFailed(transactionHash: result2.transactionHash) + } + + func testExecuteV3FeeMultipliers() async throws { + let recipientAddress = AccountTests.devnetClient.constants.predeployedAccount2.address + + let calldata: [Felt] = [recipientAddress, 1000, 0] + let call = StarknetCall(contractAddress: ethContractAddress, entrypoint: starknetSelector(from: "transfer"), calldata: calldata) + + let result = try await account.executeV3(call: call, estimateAmountMultiplier: 1.8, estimateUnitPriceMultiplier: 1.8) + try await Self.devnetClient.assertTransactionSucceeded(transactionHash: result.transactionHash) + + let result2 = try await account.executeV3(call: call, estimateAmountMultiplier: 0.9, estimateUnitPriceMultiplier: 1.0) + try await Self.devnetClient.assertTransactionFailed(transactionHash: result2.transactionHash) + } + + func testExecuteV1CustomParams() async throws { let recipientAddress = AccountTests.devnetClient.constants.predeployedAccount2.address let calldata: [Felt] = [ @@ -121,7 +147,7 @@ final class AccountTests: XCTestCase { try await Self.devnetClient.assertTransactionSucceeded(transactionHash: result.transactionHash) } - func testExecuteMultipleCalls() async throws { + func testExecuteV1MultipleCalls() async throws { let recipientAddress = AccountTests.devnetClient.constants.predeployedAccount2.address let calldata1: [Felt] = [ @@ -144,7 +170,7 @@ final class AccountTests: XCTestCase { try await Self.devnetClient.assertTransactionSucceeded(transactionHash: result.transactionHash) } - func testDeployAccount() async throws { + func testDeployAccountV1() async throws { let newSigner = StarkCurveSigner(privateKey: 1234)! let newPublicKey = newSigner.publicKey let newAccountAddress = StarknetContractAddressCalculator.calculateFrom(classHash: accountContractClassHash, calldata: [newPublicKey], salt: .zero) diff --git a/Tests/StarknetTests/Crypto/FeeEstimateTests.swift b/Tests/StarknetTests/Crypto/FeeEstimateTests.swift index 97b7fa007..b39a03f17 100644 --- a/Tests/StarknetTests/Crypto/FeeEstimateTests.swift +++ b/Tests/StarknetTests/Crypto/FeeEstimateTests.swift @@ -6,16 +6,21 @@ final class FeeEstimateTests: XCTestCase { func testEstimateFeeToResourceBounds() { let cases: [(StarknetFeeEstimate, Double, Double, StarknetResourceBounds)] = [ - (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 2138, overallFee: 21380, feeUnit: .wei), 0.1, 0.5, StarknetResourceBounds(maxAmount: 11, maxPricePerUnit: 3207)), - (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 1000, overallFee: 10000, feeUnit: .wei), 0, 0, StarknetResourceBounds(maxAmount: 10, maxPricePerUnit: 1000)), - (StarknetFeeEstimate(gasConsumed: Felt(UInt64AsHex.max.value - 100)!, gasPrice: Felt(UInt128AsHex.max.value - 100)!, overallFee: Felt.max, feeUnit: .wei), 0.1, 0.5, StarknetResourceBounds(maxAmount: UInt64AsHex.max, maxPricePerUnit: UInt128AsHex.max)), - (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 0, overallFee: 0, feeUnit: .wei), 0.5, 0.5, StarknetResourceBounds(maxAmount: 15, maxPricePerUnit: 0)), - (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 2000, overallFee: 20000, feeUnit: .wei), 1, 1, StarknetResourceBounds(maxAmount: 20, maxPricePerUnit: 4000)), + (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 2138, dataGasConsumed: 10, dataGasPrice: 1, overallFee: 21380, feeUnit: .wei), 1.1, 1.5, StarknetResourceBounds(maxAmount: 11, maxPricePerUnit: 3207)), + (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 1000, dataGasConsumed: 10, dataGasPrice: 1, overallFee: 10000, feeUnit: .wei), 1.0, 1.0, StarknetResourceBounds(maxAmount: 10, maxPricePerUnit: 1000)), + (StarknetFeeEstimate(gasConsumed: Felt(UInt64AsHex.max.value - 100)!, gasPrice: Felt(UInt128AsHex.max.value - 100)!, dataGasConsumed: Felt.max, dataGasPrice: 10, overallFee: Felt.max, feeUnit: .wei), 1.1, 1.5, StarknetResourceBounds(maxAmount: UInt64AsHex.max, maxPricePerUnit: UInt128AsHex.max)), + (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 0, dataGasConsumed: 10, dataGasPrice: 1, overallFee: 10, feeUnit: .wei), 1.5, 1.5, StarknetResourceBounds(maxAmount: 0, maxPricePerUnit: 0)), + (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 2000, dataGasConsumed: 10, dataGasPrice: 1, overallFee: 20000, feeUnit: .wei), 2, 2, StarknetResourceBounds(maxAmount: 20, maxPricePerUnit: 4000)), ] cases.forEach { - let resourceBounds = $0.toResourceBounds(amountOverhead: $1, unitPriceOverhead: $2) + let resourceBounds = $0.toResourceBounds(amountMultiplier: $1, unitPriceMultiplier: $2) let expected = StarknetResourceBoundsMapping(l1Gas: $3) + + XCTAssertEqual(resourceBounds.l1Gas.maxAmount, expected.l1Gas.maxAmount) + XCTAssertEqual(resourceBounds.l1Gas.maxPricePerUnit, expected.l1Gas.maxPricePerUnit) + XCTAssertEqual(resourceBounds.l2Gas.maxAmount, expected.l2Gas.maxAmount) + XCTAssertEqual(resourceBounds.l2Gas.maxPricePerUnit, expected.l2Gas.maxPricePerUnit) XCTAssertEqual(resourceBounds, expected) } } @@ -23,15 +28,15 @@ final class FeeEstimateTests: XCTestCase { func testEstimateFeeToMaxFee() { let cases: [(StarknetFeeEstimate, Double, Felt)] = [ - (StarknetFeeEstimate(gasConsumed: 1, gasPrice: 2138, overallFee: 2138, feeUnit: .wei), 0.1, 2351), - (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 1000, overallFee: 10000, feeUnit: .wei), 0, 10000), - (StarknetFeeEstimate(gasConsumed: Felt(UInt64AsHex.max.value - 100)!, gasPrice: Felt(UInt128AsHex.max.value - 100)!, overallFee: Felt.max, feeUnit: .wei), 0.1, Felt.max), - (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 0, overallFee: 0, feeUnit: .wei), 0.5, 0), - (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 2000, overallFee: 20000, feeUnit: .wei), 1, 40000), + (StarknetFeeEstimate(gasConsumed: 1, gasPrice: 2138, dataGasConsumed: 10, dataGasPrice: 1, overallFee: 2138, feeUnit: .wei), 1.1, 2351), + (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 1000, dataGasConsumed: 10, dataGasPrice: 1, overallFee: 10000, feeUnit: .wei), 1.0, 10000), + (StarknetFeeEstimate(gasConsumed: Felt(UInt64AsHex.max.value - 100)!, gasPrice: Felt(UInt128AsHex.max.value - 100)!, dataGasConsumed: 10, dataGasPrice: 1, overallFee: Felt.max, feeUnit: .wei), 1.1, Felt.max), + (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 0, dataGasConsumed: 10, dataGasPrice: 1, overallFee: 0, feeUnit: .wei), 1.5, 0), + (StarknetFeeEstimate(gasConsumed: 10, gasPrice: 2000, dataGasConsumed: 10, dataGasPrice: 1, overallFee: 20000, feeUnit: .wei), 2, 40000), ] cases.forEach { - let estimated = $0.toMaxFee(overhead: $1) + let estimated = $0.toMaxFee(multiplier: $1) XCTAssertEqual(estimated, $2) } } diff --git a/Tests/StarknetTests/Data/TransactionReceiptTests.swift b/Tests/StarknetTests/Data/TransactionReceiptTests.swift index 708f6cdf5..751e83104 100644 --- a/Tests/StarknetTests/Data/TransactionReceiptTests.swift +++ b/Tests/StarknetTests/Data/TransactionReceiptTests.swift @@ -2,7 +2,7 @@ import XCTest @testable import Starknet -let invokeReceipt = """ +let invokeReceiptWithBlockInfo = """ { "type": "INVOKE", "transaction_hash": "0x333198614194ae5b5ef921e63898a592de5e9f4d7b6e04745093da88b429f2a", @@ -16,10 +16,10 @@ let invokeReceipt = """ "events": [], "execution_status": "SUCCEEDED", "finality_status": "ACCEPTED_ON_L2", - "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1} + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "segment_arena_builtin": 2, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}} } """ -let pendingInvokeReceipt = """ +let invokeReceipt = """ { "type": "INVOKE", "transaction_hash": "0x333198614194ae5b5ef921e63898a592de5e9f4d7b6e04745093da88b429f2a", @@ -31,10 +31,10 @@ let pendingInvokeReceipt = """ "events": [], "execution_status": "SUCCEEDED", "finality_status": "ACCEPTED_ON_L2", - "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1} + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "segment_arena_builtin": 2, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}} } """ -let declareReceipt = """ +let declareReceiptWithBlockInfo = """ { "type": "DECLARE", "transaction_hash": "0x333198614194ae5b5ef921e63898a592de5e9f4d7b6e04745093da88b429f2a", @@ -48,10 +48,10 @@ let declareReceipt = """ "events": [], "execution_status": "SUCCEEDED", "finality_status": "ACCEPTED_ON_L2", - "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1} + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "segment_arena_builtin": 2, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}} } """ -let pendingDeclareReceipt = """ +let declareReceipt = """ { "type": "DECLARE", "transaction_hash": "0x333198614194ae5b5ef921e63898a592de5e9f4d7b6e04745093da88b429f2a", @@ -63,10 +63,10 @@ let pendingDeclareReceipt = """ "events": [], "execution_status": "SUCCEEDED", "finality_status": "ACCEPTED_ON_L2", - "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1} + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "segment_arena_builtin": 2, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}} } """ -let deployAccountReceipt = """ +let deployAccountReceiptWithBlockInfo = """ { "type": "DEPLOY_ACCOUNT", "transaction_hash": "0x333198614194ae5b5ef921e63898a592de5e9f4d7b6e04745093da88b429f2a", @@ -80,11 +80,11 @@ let deployAccountReceipt = """ "events": [], "execution_status": "SUCCEEDED", "finality_status": "ACCEPTED_ON_L2", - "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1}, + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "segment_arena_builtin": 2, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}}, "contract_address": "0x789" } """ -let pendingDeployAccountReceipt = """ +let deployAccountReceipt = """ { "type": "DEPLOY_ACCOUNT", "transaction_hash": "0x333198614194ae5b5ef921e63898a592de5e9f4d7b6e04745093da88b429f2a", @@ -96,11 +96,11 @@ let pendingDeployAccountReceipt = """ "events": [], "execution_status": "SUCCEEDED", "finality_status": "ACCEPTED_ON_L2", - "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1}, + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "segment_arena_builtin": 2, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}}, "contract_address": "0x789" } """ -let deployReceipt = """ +let deployReceiptWithBlockInfo = """ { "type": "DEPLOY", "transaction_hash": "0x333198614194ae5b5ef921e63898a592de5e9f4d7b6e04745093da88b429f2a", @@ -114,11 +114,27 @@ let deployReceipt = """ "events": [], "execution_status": "SUCCEEDED", "finality_status": "ACCEPTED_ON_L2", - "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1}, + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "segment_arena_builtin": 2, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}}, "contract_address": "0x789" } """ -let l1HandlerReceipt = """ +let deployReceipt = """ +{ + "type": "DEPLOY", + "transaction_hash": "0x333198614194ae5b5ef921e63898a592de5e9f4d7b6e04745093da88b429f2a", + "actual_fee": { + "amount": "0x244adfc7e22", + "unit": "FRI" + }, + "messages_sent": [], + "events": [], + "execution_status": "SUCCEEDED", + "finality_status": "ACCEPTED_ON_L2", + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}}, + "contract_address": "0x789" +} +""" +let l1HandlerReceiptWithBlockInfo = """ { "type": "L1_HANDLER", "transaction_hash": "0x333198614194ae5b5ef921e63898a592de5e9f4d7b6e04745093da88b429f2a", @@ -132,11 +148,11 @@ let l1HandlerReceipt = """ "events": [], "execution_status": "SUCCEEDED", "finality_status": "ACCEPTED_ON_L2", - "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1}, + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "segment_arena_builtin": 2, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}}, "message_hash":"0x2137" } """ -let pendingL1HandlerReceipt = """ +let l1HandlerReceipt = """ { "type": "L1_HANDLER", "transaction_hash": "0x333198614194ae5b5ef921e63898a592de5e9f4d7b6e04745093da88b429f2a", @@ -148,7 +164,7 @@ let pendingL1HandlerReceipt = """ "events": [], "execution_status": "SUCCEEDED", "finality_status": "ACCEPTED_ON_L2", - "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1}, + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "segment_arena_builtin": 2, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}}, "message_hash":"0x2137" } """ @@ -156,27 +172,30 @@ let pendingL1HandlerReceipt = """ final class TransactionReceiptTests: XCTestCase { func testTransactionReceiptWrapperDecoding() throws { let cases: [(String, StarknetTransactionType, Bool, any StarknetTransactionReceipt.Type)] = [ - (invokeReceipt, .invoke, false, StarknetProcessedInvokeTransactionReceipt.self), - (declareReceipt, .declare, false, StarknetProcessedDeclareTransactionReceipt.self), - (deployAccountReceipt, .deployAccount, false, StarknetProcessedDeployAccountTransactionReceipt.self), - (l1HandlerReceipt, .l1Handler, false, StarknetProcessedL1HandlerTransactionReceipt.self), - (deployReceipt, .deploy, false, StarknetProcessedDeployTransactionReceipt.self), - (pendingInvokeReceipt, .invoke, true, StarknetPendingInvokeTransactionReceipt.self), - (pendingDeclareReceipt, .declare, true, StarknetPendingDeclareTransactionReceipt.self), - (pendingDeployAccountReceipt, .deployAccount, true, StarknetPendingDeployAccountTransactionReceipt.self), - (pendingL1HandlerReceipt, .l1Handler, true, StarknetPendingL1HandlerTransactionReceipt.self), + (invokeReceiptWithBlockInfo, .invoke, true, StarknetInvokeTransactionReceipt.self), + (declareReceiptWithBlockInfo, .declare, true, StarknetDeclareTransactionReceipt.self), + (deployAccountReceiptWithBlockInfo, .deployAccount, true, StarknetDeployAccountTransactionReceipt.self), + (l1HandlerReceiptWithBlockInfo, .l1Handler, true, StarknetL1HandlerTransactionReceipt.self), + (deployReceiptWithBlockInfo, .deploy, true, StarknetDeployTransactionReceipt.self), + (invokeReceipt, .invoke, false, StarknetInvokeTransactionReceipt.self), + (declareReceipt, .declare, false, StarknetDeclareTransactionReceipt.self), + (deployAccountReceipt, .deployAccount, false, StarknetDeployAccountTransactionReceipt.self), + (l1HandlerReceipt, .l1Handler, false, StarknetL1HandlerTransactionReceipt.self), + (deployReceipt, .deploy, false, StarknetDeployTransactionReceipt.self), ] - try cases.forEach { (string: String, txType: StarknetTransactionType, isPending: Bool, receiptType: StarknetTransactionReceipt.Type) in + try cases.forEach { (string: String, txType: StarknetTransactionType, hasBlockInfo: Bool, receiptType: StarknetTransactionReceipt.Type) in let data = string.data(using: .utf8)! let decoder = JSONDecoder() let receiptWrapper = try decoder.decode(TransactionReceiptWrapper.self, from: data) let receipt = receiptWrapper.transactionReceipt - if isPending { - XCTAssertTrue(receipt is (any StarknetPendingTransactionReceipt)) + if hasBlockInfo { + XCTAssertNotNil(receipt.blockNumber) + XCTAssertNotNil(receipt.blockHash) } else { - XCTAssertTrue(receipt is (any StarknetProcessedTransactionReceipt)) + XCTAssertNil(receipt.blockNumber) + XCTAssertNil(receipt.blockHash) } XCTAssertTrue(type(of: receipt) == receiptType) @@ -236,7 +255,7 @@ final class TransactionReceiptTests: XCTestCase { ], "execution_status": "SUCCEEDED", "finality_status": "ACCEPTED_ON_L1", - "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1} + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "segment_arena_builtin": 2, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}} } """.data(using: .utf8)! @@ -266,7 +285,7 @@ final class TransactionReceiptTests: XCTestCase { "revert_reason": "Error in the called contract (0x03b1b7a7ae9a136a327b01b89ddfee24a474c74bf76032876b5754e44cd7040b):\\nError at pc=0:32:\\nGot an exception while executing a hint: Custom Hint Error: Requested contract address ContractAddress(PatriciaKey(StarkFelt(\\"0x0000000000000000000000000000000000000000000000000000000000000042\\"))) is not deployed.\\nCairo traceback (most recent call last):\\nUnknown location (pc=0:557)\\nUnknown location (pc=0:519)\\nUnknown location (pc=0:625)\\n", "execution_status": "REVERTED", "finality_status": "ACCEPTED_ON_L1", - "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1} + "execution_resources": {"steps": 999, "memory_holes" : 1, "range_check_builtin_applications": 21, "pedersen_builtin_applications": 37, "poseidon_builtin_applications": 451, "ec_op_builtin_applications": 123, "ecdsa_builtin_applications": 789, "bitwise_builtin_applications": 1, "keccak_builtin_applications": 1, "segment_arena_builtin": 2, "data_availability": {"l1_gas": 123, "l1_data_gas": 456}} } """.data(using: .utf8)! diff --git a/Tests/StarknetTests/Data/TransactionTests.swift b/Tests/StarknetTests/Data/TransactionTests.swift index c06c6bfb2..ea56cb5e8 100644 --- a/Tests/StarknetTests/Data/TransactionTests.swift +++ b/Tests/StarknetTests/Data/TransactionTests.swift @@ -71,21 +71,21 @@ final class TransactionTests: XCTestCase { } func testTransactionWrapperDecoding() throws { - let cases: [(String, StarknetTransactionType, Felt)] = [ - (invokeTransactionV3, .invoke, 3), - (invokeTransactionV1, .invoke, 1), - (invokeTransactionV0, .invoke, 0), - (declareTransactinoV0, .declare, 0), - (declareTransactionV1, .declare, 1), - (declareTransactionV2, .declare, 2), - (declareTransactionV3, .declare, 3), - (deployTransaction, .deploy, 0), - (deployAccountTransactionV1, .deployAccount, 1), - (deployAccountTransactionV3, .deployAccount, 3), - (l1HandlerTransaction, .l1Handler, 0), + let cases: [(String, StarknetTransactionType, StarknetTransactionVersion)] = [ + (invokeTransactionV3, .invoke, .v3), + (invokeTransactionV1, .invoke, .v1), + (invokeTransactionV0, .invoke, .v0), + (declareTransactinoV0, .declare, .v0), + (declareTransactionV1, .declare, .v1), + (declareTransactionV2, .declare, .v2), + (declareTransactionV3, .declare, .v3), + (deployTransaction, .deploy, .v0), + (deployAccountTransactionV1, .deployAccount, .v1), + (deployAccountTransactionV3, .deployAccount, .v3), + (l1HandlerTransaction, .l1Handler, .v0), ] - try cases.forEach { (string: String, type: StarknetTransactionType, version: Felt) in + try cases.forEach { (string: String, type: StarknetTransactionType, version: StarknetTransactionVersion) in let data = string.data(using: .utf8)! let decoder = JSONDecoder() diff --git a/Tests/StarknetTests/Providers/ProviderTests.swift b/Tests/StarknetTests/Providers/ProviderTests.swift index 9d22fffd8..b11ae20da 100644 --- a/Tests/StarknetTests/Providers/ProviderTests.swift +++ b/Tests/StarknetTests/Providers/ProviderTests.swift @@ -36,7 +36,7 @@ final class ProviderTests: XCTestCase { signer = StarkCurveSigner(privateKey: accountDetails.privateKey)! chainId = try await provider.getChainId() - account = StarknetAccount(address: accountDetails.address, signer: signer, provider: provider, chainId: chainId, cairoVersion: .zero) + account = StarknetAccount(address: accountDetails.address, signer: signer, provider: provider, chainId: chainId, cairoVersion: .one) } func makeStarknetProvider(url: String) -> StarknetProviderProtocol { @@ -83,7 +83,7 @@ final class ProviderTests: XCTestCase { func testCallWithArguments() async throws { let call = StarknetCall( contractAddress: ProviderTests.devnetClient.constants.predeployedAccount1.address, - entrypoint: starknetSelector(from: "supportsInterface"), + entrypoint: starknetSelector(from: "supports_interface"), calldata: [Felt(2138)] ) @@ -308,7 +308,7 @@ final class ProviderTests: XCTestCase { XCTAssertNotEqual(Felt.zero, feeEstimate.gasPrice) XCTAssertNotEqual(Felt.zero, feeEstimate.gasConsumed) XCTAssertNotEqual(Felt.zero, feeEstimate.overallFee) - XCTAssertEqual(feeEstimate.gasPrice.value * feeEstimate.gasConsumed.value, feeEstimate.overallFee.value) + XCTAssertEqual(feeEstimate.gasPrice.value * feeEstimate.gasConsumed.value + feeEstimate.dataGasPrice.value * feeEstimate.dataGasConsumed.value, feeEstimate.overallFee.value) } func testSimulateTransactionsV1() async throws { diff --git a/Tests/StarknetTests/Utils/DevnetClient/DevnetClient.swift b/Tests/StarknetTests/Utils/DevnetClient/DevnetClient.swift index 01a5123d2..52f55cd8d 100644 --- a/Tests/StarknetTests/Utils/DevnetClient/DevnetClient.swift +++ b/Tests/StarknetTests/Utils/DevnetClient/DevnetClient.swift @@ -34,7 +34,7 @@ protocol DevnetClientProtocol { } extension DevnetClientProtocol { - func prefundAccount(address: Felt, amount: UInt64 = 5_000_000_000_000_000, unit: StarknetPriceUnit = .wei) async throws { + func prefundAccount(address: Felt, amount: UInt64 = 5_000_000_000_000_000_000, unit: StarknetPriceUnit = .wei) async throws { try await prefundAccount(address: address, amount: amount, unit: unit) } @@ -90,7 +90,7 @@ extension DevnetClientProtocol { try await deployAccount(name: name, classHash: classHash, maxFee: maxFee, prefund: prefund) } - func declareContract(contractName: String, maxFee: Felt = 1_000_000_000_000_000) async throws -> DeclareContractResult { + func declareContract(contractName: String, maxFee: Felt = 10_000_000_000_000_000) async throws -> DeclareContractResult { try await declareContract(contractName: contractName, maxFee: maxFee) } @@ -99,7 +99,7 @@ extension DevnetClientProtocol { constructorCalldata: [Felt] = [], salt: Felt? = .zero, unique: Bool = false, - maxFeeDeclare: Felt = 1_000_000_000_000_000, + maxFeeDeclare: Felt = 10_000_000_000_000_000, maxFeeDeploy: Felt = 1_000_000_000_000_000 ) async throws -> DeclareDeployContractResult { try await declareDeployContract( @@ -432,7 +432,7 @@ func makeDevnetClient() -> DevnetClientProtocol { constructorCalldata: [Felt] = [], salt: Felt? = nil, unique: Bool = false, - maxFeeDeclare: Felt = 1_000_000_000_000_000, + maxFeeDeclare: Felt = 10_000_000_000_000_000, maxFeeDeploy: Felt = 1_000_000_000_000_000 ) async throws -> DeclareDeployContractResult { try guardDevnetIsRunning()