diff --git a/lib/src/main/kotlin/com/swmansion/starknet/account/Account.kt b/lib/src/main/kotlin/com/swmansion/starknet/account/Account.kt index 32ed24d42..b595b83db 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/account/Account.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/account/Account.kt @@ -2,7 +2,6 @@ package com.swmansion.starknet.account import com.swmansion.starknet.data.TypedData import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* import com.swmansion.starknet.provider.Request /** @@ -396,7 +395,7 @@ interface Account { * @param call a call used to estimate a fee. * @return Field value representing estimated fee. */ - fun estimateFeeV1(call: Call): Request> + fun estimateFeeV1(call: Call): Request /** * Estimate fee for a call as a version 3 invoke transaction. @@ -406,7 +405,7 @@ interface Account { * @param call a call used to estimate a fee. * @return Field value representing estimated fee. */ - fun estimateFeeV3(call: Call): Request> + fun estimateFeeV3(call: Call): Request /** * Estimate fee for a call as a version 1 invoke transaction. @@ -417,7 +416,7 @@ interface Account { * @param skipValidate when set to `true`, the validation part of the transaction is skipped. * @return Field value representing estimated fee. */ - fun estimateFeeV1(call: Call, skipValidate: Boolean): Request> + fun estimateFeeV1(call: Call, skipValidate: Boolean): Request /** * Estimate fee for a call as a version 3 invoke transaction. @@ -428,7 +427,7 @@ interface Account { * @param skipValidate when set to `true`, the validation part of the transaction is skipped. * @return Field value representing estimated fee. */ - fun estimateFeeV3(call: Call, skipValidate: Boolean): Request> + fun estimateFeeV3(call: Call, skipValidate: Boolean): Request /** * Estimate fee for a call as a version 1 invoke transaction. @@ -439,7 +438,7 @@ interface Account { * @param blockTag a tag of the block in respect to what the query will be made. * @return Field value representing estimated fee. */ - fun estimateFeeV1(call: Call, blockTag: BlockTag): Request> + fun estimateFeeV1(call: Call, blockTag: BlockTag): Request /** * Estimate fee for a call as a version 3 invoke transaction. @@ -450,7 +449,7 @@ interface Account { * @param blockTag a tag of the block in respect to what the query will be made. * @return Field value representing estimated fee. */ - fun estimateFeeV3(call: Call, blockTag: BlockTag): Request> + fun estimateFeeV3(call: Call, blockTag: BlockTag): Request /** * Estimate fee for a call as a version 1 invoke transaction. @@ -462,7 +461,7 @@ interface Account { * @param skipValidate when set to `true`, the validation part of the transaction is skipped. * @return Field value representing estimated fee. */ - fun estimateFeeV1(call: Call, blockTag: BlockTag, skipValidate: Boolean): Request> + fun estimateFeeV1(call: Call, blockTag: BlockTag, skipValidate: Boolean): Request /** * Estimate fee for a call as a version 3 invoke transaction. @@ -474,7 +473,7 @@ interface Account { * @param skipValidate when set to `true`, the validation part of the transaction is skipped. * @return Field value representing estimated fee. */ - fun estimateFeeV3(call: Call, blockTag: BlockTag, skipValidate: Boolean): Request> + fun estimateFeeV3(call: Call, blockTag: BlockTag, skipValidate: Boolean): Request /** * Estimate fee for a list of calls as a version 1 invoke transaction. @@ -484,7 +483,7 @@ interface Account { * @param calls a list of calls used to estimate a fee. * @return estimated fee as field value. */ - fun estimateFeeV1(calls: List): Request> + fun estimateFeeV1(calls: List): Request /** * Estimate fee for a list of calls as a version 3 invoke transaction. @@ -494,7 +493,7 @@ interface Account { * @param calls a list of calls used to estimate a fee. * @return estimated fee as field value. */ - fun estimateFeeV3(calls: List): Request> + fun estimateFeeV3(calls: List): Request /** * Estimate fee for a list of calls as a version 1 invoke transaction. @@ -505,7 +504,7 @@ interface Account { * @param skipValidate when set to `true`, the validation part of the transaction is skipped. * @return estimated fee as field value. */ - fun estimateFeeV1(calls: List, skipValidate: Boolean): Request> + fun estimateFeeV1(calls: List, skipValidate: Boolean): Request /** * Estimate fee for a list of calls as a version 3 invoke transaction. @@ -516,7 +515,7 @@ interface Account { * @param skipValidate when set to `true`, the validation part of the transaction is skipped. * @return estimated fee as field value. */ - fun estimateFeeV3(calls: List, skipValidate: Boolean): Request> + fun estimateFeeV3(calls: List, skipValidate: Boolean): Request /** * Estimate fee for a list of calls as a version 1 invoke transaction. @@ -527,7 +526,7 @@ interface Account { * @param blockTag a tag of the block in respect to what the query will be made. * @return estimated fee as field value. */ - fun estimateFeeV1(calls: List, blockTag: BlockTag): Request> + fun estimateFeeV1(calls: List, blockTag: BlockTag): Request /** * Estimate fee for a list of calls. @@ -538,7 +537,7 @@ interface Account { * @param blockTag a tag of the block in respect to what the query will be made. * @return estimated fee as field value. */ - fun estimateFeeV3(calls: List, blockTag: BlockTag): Request> + fun estimateFeeV3(calls: List, blockTag: BlockTag): Request /** * Estimate fee for a list of calls using version 3 invoke transaction. @@ -554,7 +553,7 @@ interface Account { calls: List, blockTag: BlockTag, skipValidate: Boolean, - ): Request> + ): Request /** * Estimate fee for a list of calls. @@ -570,7 +569,7 @@ interface Account { calls: List, blockTag: BlockTag, skipValidate: Boolean, - ): Request> + ): Request /** * Get account nonce. diff --git a/lib/src/main/kotlin/com/swmansion/starknet/account/StandardAccount.kt b/lib/src/main/kotlin/com/swmansion/starknet/account/StandardAccount.kt index acf0acedc..58ae07ad6 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/account/StandardAccount.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/account/StandardAccount.kt @@ -2,8 +2,7 @@ package com.swmansion.starknet.account import com.swmansion.starknet.data.TypedData import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* -import com.swmansion.starknet.data.types.transactions.DeployAccountTransactionV1Payload +import com.swmansion.starknet.data.types.DeployAccountTransactionV1Payload import com.swmansion.starknet.extensions.compose import com.swmansion.starknet.extensions.toFelt import com.swmansion.starknet.provider.Provider @@ -241,7 +240,7 @@ class StandardAccount @JvmOverloads constructor( override fun executeV1(calls: List, estimateFeeMultiplier: Double): Request { return estimateFeeV1(calls).compose { estimateFee -> - val maxFee = estimateFee.first().toMaxFee(estimateFeeMultiplier) + val maxFee = estimateFee.values.first().toMaxFee(estimateFeeMultiplier) executeV1(calls, maxFee) } } @@ -252,7 +251,7 @@ class StandardAccount @JvmOverloads constructor( estimateUnitPriceMultiplier: Double, ): Request { return estimateFeeV3(calls).compose { estimateFee -> - val resourceBounds = estimateFee.first().toResourceBounds( + val resourceBounds = estimateFee.values.first().toResourceBounds( amountMultiplier = estimateAmountMultiplier, unitPriceMultiplier = estimateUnitPriceMultiplier, ) @@ -262,14 +261,14 @@ class StandardAccount @JvmOverloads constructor( override fun executeV1(calls: List): Request { return estimateFeeV1(calls).compose { estimateFee -> - val maxFee = estimateFee.first().toMaxFee() + val maxFee = estimateFee.values.first().toMaxFee() executeV1(calls, maxFee) } } override fun executeV3(calls: List): Request { return estimateFeeV3(calls).compose { estimateFee -> - val resourceBounds = estimateFee.first().toResourceBounds() + val resourceBounds = estimateFee.values.first().toResourceBounds() executeV3(calls, resourceBounds.l1Gas) } } @@ -314,27 +313,27 @@ class StandardAccount @JvmOverloads constructor( override fun getNonce(blockNumber: Int) = provider.getNonce(address, blockNumber) - override fun estimateFeeV1(call: Call): Request> { + override fun estimateFeeV1(call: Call): Request { return estimateFeeV1(listOf(call)) } - override fun estimateFeeV3(call: Call): Request> { + override fun estimateFeeV3(call: Call): Request { return estimateFeeV3(listOf(call)) } - override fun estimateFeeV1(call: Call, skipValidate: Boolean): Request> { + override fun estimateFeeV1(call: Call, skipValidate: Boolean): Request { return estimateFeeV1(listOf(call), skipValidate) } - override fun estimateFeeV3(call: Call, skipValidate: Boolean): Request> { + override fun estimateFeeV3(call: Call, skipValidate: Boolean): Request { return estimateFeeV3(listOf(call), skipValidate) } - override fun estimateFeeV1(call: Call, blockTag: BlockTag): Request> { + override fun estimateFeeV1(call: Call, blockTag: BlockTag): Request { return estimateFeeV1(listOf(call), blockTag) } - override fun estimateFeeV3(call: Call, blockTag: BlockTag): Request> { + override fun estimateFeeV3(call: Call, blockTag: BlockTag): Request { return estimateFeeV3(listOf(call), blockTag) } @@ -342,7 +341,7 @@ class StandardAccount @JvmOverloads constructor( call: Call, blockTag: BlockTag, skipValidate: Boolean, - ): Request> { + ): Request { return estimateFeeV1(listOf(call), blockTag, skipValidate) } @@ -350,31 +349,31 @@ class StandardAccount @JvmOverloads constructor( call: Call, blockTag: BlockTag, skipValidate: Boolean, - ): Request> { + ): Request { return estimateFeeV3(listOf(call), blockTag, skipValidate) } - override fun estimateFeeV1(calls: List): Request> { + override fun estimateFeeV1(calls: List): Request { return estimateFeeV1(calls, BlockTag.PENDING, false) } - override fun estimateFeeV3(calls: List): Request> { + override fun estimateFeeV3(calls: List): Request { return estimateFeeV3(calls, BlockTag.PENDING, false) } - override fun estimateFeeV1(calls: List, skipValidate: Boolean): Request> { + override fun estimateFeeV1(calls: List, skipValidate: Boolean): Request { return estimateFeeV1(calls, BlockTag.PENDING, skipValidate) } - override fun estimateFeeV3(calls: List, skipValidate: Boolean): Request> { + override fun estimateFeeV3(calls: List, skipValidate: Boolean): Request { return estimateFeeV3(calls, BlockTag.PENDING, skipValidate) } - override fun estimateFeeV1(calls: List, blockTag: BlockTag): Request> { + override fun estimateFeeV1(calls: List, blockTag: BlockTag): Request { return estimateFeeV1(calls, blockTag, false) } - override fun estimateFeeV3(calls: List, blockTag: BlockTag): Request> { + override fun estimateFeeV3(calls: List, blockTag: BlockTag): Request { return estimateFeeV3(calls, blockTag, false) } @@ -382,7 +381,7 @@ class StandardAccount @JvmOverloads constructor( calls: List, blockTag: BlockTag, skipValidate: Boolean, - ): Request> { + ): Request { return getNonce(blockTag).compose { nonce -> val simulationFlags = prepareSimulationFlagsForFeeEstimate(skipValidate) val payload = buildEstimateFeeV1Payload(calls, nonce) @@ -394,7 +393,7 @@ class StandardAccount @JvmOverloads constructor( calls: List, blockTag: BlockTag, skipValidate: Boolean, - ): Request> { + ): Request { return getNonce(blockTag).compose { nonce -> val payload = buildEstimateFeeV3Payload(calls, nonce) val simulationFlags = prepareSimulationFlagsForFeeEstimate(skipValidate) diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/TransactionHashCalculator.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/TransactionHashCalculator.kt index 17fb048d0..b38337126 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/TransactionHashCalculator.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/TransactionHashCalculator.kt @@ -3,9 +3,9 @@ package com.swmansion.starknet.data import com.swmansion.starknet.crypto.Poseidon import com.swmansion.starknet.crypto.StarknetCurve import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.DAMode -import com.swmansion.starknet.data.types.transactions.TransactionType -import com.swmansion.starknet.data.types.transactions.TransactionVersion +import com.swmansion.starknet.data.types.DAMode +import com.swmansion.starknet.data.types.TransactionType +import com.swmansion.starknet.data.types.TransactionVersion import com.swmansion.starknet.extensions.toFelt /** diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/BlockPolymorphicSerializer.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/BlockPolymorphicSerializer.kt index 2f14d9fd6..bcfdbfd2d 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/BlockPolymorphicSerializer.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/BlockPolymorphicSerializer.kt @@ -1,7 +1,6 @@ package com.swmansion.starknet.data.serializers import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.KSerializer import kotlinx.serialization.descriptors.PrimitiveKind diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/EstimateFeeResponseListSerializer.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/EstimateFeeResponseListSerializer.kt new file mode 100644 index 000000000..90789b55e --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/EstimateFeeResponseListSerializer.kt @@ -0,0 +1,27 @@ +package com.swmansion.starknet.data.serializers + +import com.swmansion.starknet.data.types.EstimateFeeResponse +import com.swmansion.starknet.data.types.EstimateFeeResponseList +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.listSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal object EstimateFeeResponseListSerializer : KSerializer { + private val listSerializer = ListSerializer(EstimateFeeResponse.serializer()) + + @OptIn(ExperimentalSerializationApi::class) + override val descriptor: SerialDescriptor = listSerialDescriptor() + + override fun serialize(encoder: Encoder, value: EstimateFeeResponseList) { + encoder.encodeSerializableValue(listSerializer, value.values) + } + + override fun deserialize(decoder: Decoder): EstimateFeeResponseList { + val list = decoder.decodeSerializableValue(listSerializer) + return EstimateFeeResponseList(list) + } +} diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/IntResponseSerializer.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/IntResponseSerializer.kt new file mode 100644 index 000000000..61fe4542b --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/IntResponseSerializer.kt @@ -0,0 +1,21 @@ +package com.swmansion.starknet.data.serializers + +import com.swmansion.starknet.data.types.IntResponse +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal object IntResponseSerializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("IntResponse", PrimitiveKind.INT) + + override fun serialize(encoder: Encoder, value: IntResponse) { + encoder.encodeInt(value.value) + } + + override fun deserialize(decoder: Decoder): IntResponse { + return IntResponse(decoder.decodeInt()) + } +} diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/SimulatedTransactionListSerializer.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/SimulatedTransactionListSerializer.kt new file mode 100644 index 000000000..9af041fe4 --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/SimulatedTransactionListSerializer.kt @@ -0,0 +1,27 @@ +package com.swmansion.starknet.data.serializers + +import com.swmansion.starknet.data.types.SimulatedTransaction +import com.swmansion.starknet.data.types.SimulatedTransactionList +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.listSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal object SimulatedTransactionListSerializer : KSerializer { + private val listSerializer = ListSerializer(SimulatedTransaction.serializer()) + + @OptIn(ExperimentalSerializationApi::class) + override val descriptor: SerialDescriptor = listSerialDescriptor() + + override fun serialize(encoder: Encoder, value: SimulatedTransactionList) { + encoder.encodeSerializableValue(listSerializer, value.values) + } + + override fun deserialize(decoder: Decoder): SimulatedTransactionList { + val list = decoder.decodeSerializableValue(listSerializer) + return SimulatedTransactionList(list) + } +} diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/StringResponseSerializer.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/StringResponseSerializer.kt new file mode 100644 index 000000000..9d9c615f8 --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/StringResponseSerializer.kt @@ -0,0 +1,21 @@ +package com.swmansion.starknet.data.serializers + +import com.swmansion.starknet.data.types.StringResponse +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal object StringResponseSerializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("StringResponse", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: StringResponse) { + encoder.encodeString(value.value) + } + + override fun deserialize(decoder: Decoder): StringResponse { + return StringResponse(decoder.decodeString()) + } +} diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionPayloadSerializer.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionPayloadSerializer.kt index b38251b98..6e958c467 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionPayloadSerializer.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionPayloadSerializer.kt @@ -1,7 +1,6 @@ package com.swmansion.starknet.data.serializers -import com.swmansion.starknet.data.types.Felt -import com.swmansion.starknet.data.types.transactions.* +import com.swmansion.starknet.data.types.* import com.swmansion.starknet.extensions.add import com.swmansion.starknet.extensions.put import kotlinx.serialization.KSerializer diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionPolymorphicSerializer.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionPolymorphicSerializer.kt index 88cbeafc2..f85e9ecc7 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionPolymorphicSerializer.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionPolymorphicSerializer.kt @@ -1,7 +1,6 @@ package com.swmansion.starknet.data.serializers -import com.swmansion.starknet.data.types.Felt -import com.swmansion.starknet.data.types.transactions.* +import com.swmansion.starknet.data.types.* import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationException import kotlinx.serialization.json.* diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionReceiptPolymorphicSerializer.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionReceiptPolymorphicSerializer.kt index b8e1a41d6..680772856 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionReceiptPolymorphicSerializer.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionReceiptPolymorphicSerializer.kt @@ -1,6 +1,6 @@ package com.swmansion.starknet.data.serializers -import com.swmansion.starknet.data.types.transactions.* +import com.swmansion.starknet.data.types.* import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationException import kotlinx.serialization.json.* diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionTracePolymorphicSerializer.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionTracePolymorphicSerializer.kt index 93e31b80f..c4aeb7d9b 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionTracePolymorphicSerializer.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/serializers/TransactionTracePolymorphicSerializer.kt @@ -1,6 +1,6 @@ package com.swmansion.starknet.data.serializers -import com.swmansion.starknet.data.types.transactions.* +import com.swmansion.starknet.data.types.* import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationException import kotlinx.serialization.json.* diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Block.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Block.kt index 1fd148f43..a5aed9781 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Block.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Block.kt @@ -3,8 +3,6 @@ package com.swmansion.starknet.data.types import com.swmansion.starknet.data.serializers.BlockIdSerializer import com.swmansion.starknet.data.serializers.TransactionPolymorphicSerializer import com.swmansion.starknet.data.serializers.TransactionReceiptPolymorphicSerializer -import com.swmansion.starknet.data.types.transactions.Transaction -import com.swmansion.starknet.data.types.transactions.TransactionReceipt import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -43,8 +41,7 @@ sealed class BlockId { } } } - -sealed interface Block { +sealed interface Block : StarknetResponse { val timestamp: Int val sequencerAddress: Felt val parentHash: Felt diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Contracts.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Contracts.kt index f64332fa1..ea2fd8678 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Contracts.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Contracts.kt @@ -264,7 +264,7 @@ data class CasmContractDefinition @JvmOverloads constructor( } } -sealed class ContractClassBase +sealed class ContractClassBase : StarknetResponse @Serializable data class DeprecatedContractClass( diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/EstimateFeeResponseList.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/EstimateFeeResponseList.kt new file mode 100644 index 000000000..035cdf0ad --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/EstimateFeeResponseList.kt @@ -0,0 +1,8 @@ +package com.swmansion.starknet.data.types + +import com.swmansion.starknet.data.serializers.EstimateFeeResponseListSerializer +import kotlinx.serialization.Serializable + +@JvmInline +@Serializable(with = EstimateFeeResponseListSerializer::class) +value class EstimateFeeResponseList(val values: List) : StarknetResponse diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Event.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Event.kt index 7981dbe7b..dad85882e 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Event.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Event.kt @@ -90,4 +90,4 @@ data class GetEventsResult( @JsonNames("continuation_token") val continuationToken: String? = "0", -) +) : StarknetResponse diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Felt.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Felt.kt index f01a4c236..cd76082e1 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Felt.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Felt.kt @@ -8,7 +8,7 @@ import kotlinx.serialization.Serializable import java.math.BigInteger @Serializable(with = FeltSerializer::class) -data class Felt(override val value: BigInteger) : NumAsHexBase(value), ConvertibleToCalldata { +data class Felt(override val value: BigInteger) : NumAsHexBase(value), ConvertibleToCalldata, StarknetResponse { constructor(value: Long) : this(BigInteger.valueOf(value)) constructor(value: Int) : this(BigInteger.valueOf(value.toLong())) diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/FeltArray.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/FeltArray.kt index 264d10016..ff9c62e10 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/FeltArray.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/FeltArray.kt @@ -2,11 +2,29 @@ package com.swmansion.starknet.data.types import com.swmansion.starknet.data.types.conversions.ConvertibleToCalldata import com.swmansion.starknet.extensions.toFelt +import kotlinx.serialization.KSerializer +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder -data class FeltArray(private val list: MutableList) : ConvertibleToCalldata, MutableList by list { +data class FeltArray(private val list: MutableList) : ConvertibleToCalldata, MutableList by list, StarknetResponse { constructor(vararg elements: Felt) : this(elements.toMutableList()) constructor(collection: Collection) : this(collection.toMutableList()) constructor() : this(emptyList()) override fun toCalldata(): List = listOf(size.toFelt) + list } + +internal object FeltArraySerializer : KSerializer { + private val delegate = ListSerializer(Felt.serializer()) + + override val descriptor = delegate.descriptor + + override fun serialize(encoder: Encoder, value: FeltArray) { + delegate.serialize(encoder, value.toList()) + } + + override fun deserialize(decoder: Decoder): FeltArray { + return FeltArray(delegate.deserialize(decoder)) + } +} diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/IntResponse.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/IntResponse.kt new file mode 100644 index 000000000..f4383eb56 --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/IntResponse.kt @@ -0,0 +1,8 @@ +package com.swmansion.starknet.data.types + +import com.swmansion.starknet.data.serializers.IntResponseSerializer +import kotlinx.serialization.Serializable + +@JvmInline +@Serializable(with = IntResponseSerializer::class) +value class IntResponse(val value: Int) : StarknetResponse diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Params.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Params.kt index b22b50f20..74fbf6218 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Params.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Params.kt @@ -2,8 +2,6 @@ package com.swmansion.starknet.data.types -import com.swmansion.starknet.data.types.transactions.DAMode - /** * Params used for signing and sending transactions. */ diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Payloads.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Payloads.kt index f9bc79271..6418dbc47 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Payloads.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Payloads.kt @@ -1,6 +1,5 @@ package com.swmansion.starknet.data.types -import com.swmansion.starknet.data.types.transactions.* import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/Resources.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Resources.kt similarity index 98% rename from lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/Resources.kt rename to lib/src/main/kotlin/com/swmansion/starknet/data/types/Resources.kt index d77cf225f..526bb6e66 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/Resources.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Resources.kt @@ -1,6 +1,6 @@ @file:JvmName("Resources") -package com.swmansion.starknet.data.types.transactions +package com.swmansion.starknet.data.types import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Responses.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Responses.kt index 42983c73c..c092e5625 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/Responses.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Responses.kt @@ -1,8 +1,6 @@ package com.swmansion.starknet.data.types import com.swmansion.starknet.data.serializers.HexToIntDeserializer -import com.swmansion.starknet.data.types.transactions.TransactionExecutionStatus -import com.swmansion.starknet.data.types.transactions.TransactionStatus import com.swmansion.starknet.extensions.* import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.SerialName @@ -19,7 +17,7 @@ data class CallContractResponse( @Serializable data class InvokeFunctionResponse( @SerialName("transaction_hash") val transactionHash: Felt, -) +) : StarknetResponse @OptIn(ExperimentalSerializationApi::class) @Serializable @@ -29,7 +27,7 @@ data class DeclareResponse( @JsonNames("class_hash") val classHash: Felt, -) +) : StarknetResponse @OptIn(ExperimentalSerializationApi::class) @Serializable @@ -40,7 +38,7 @@ data class DeployAccountResponse( // TODO: (#344) deviation from the spec, make this non-nullable once Juno is updated @JsonNames("address", "contract_address") val address: Felt? = null, -) +) : StarknetResponse @Serializable data class EstimateFeeResponse( @@ -62,7 +60,7 @@ data class EstimateFeeResponse( // TODO: (#344) Deviation from the spec, make this non-nullable once Pathfinder is updated @SerialName("unit") val feeUnit: PriceUnit? = null, -) { +) : StarknetResponse { /** * Convert estimated fee to max fee with applied multiplier. * @@ -118,7 +116,7 @@ data class GetBlockHashAndNumberResponse( @JsonNames("block_number") val blockNumber: Int, -) +) : StarknetResponse @Serializable data class GetTransactionStatusResponse( @@ -127,10 +125,10 @@ data class GetTransactionStatusResponse( @SerialName("execution_status") val executionStatus: TransactionExecutionStatus? = null, -) +) : StarknetResponse @Serializable -sealed class Syncing { +sealed class Syncing : StarknetResponse { abstract val status: Boolean abstract val startingBlockHash: Felt @@ -266,7 +264,7 @@ data class ReplacedClassItem( ) @Serializable -sealed class StateUpdate { +sealed class StateUpdate : StarknetResponse { abstract val oldRoot: Felt abstract val stateDiff: StateDiff } diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/SimulatedTransaction.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/SimulatedTransaction.kt similarity index 93% rename from lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/SimulatedTransaction.kt rename to lib/src/main/kotlin/com/swmansion/starknet/data/types/SimulatedTransaction.kt index d29479370..8cbc63b58 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/SimulatedTransaction.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/SimulatedTransaction.kt @@ -1,12 +1,6 @@ -package com.swmansion.starknet.data.types.transactions +package com.swmansion.starknet.data.types import com.swmansion.starknet.data.serializers.TransactionTracePolymorphicSerializer -import com.swmansion.starknet.data.types.Calldata -import com.swmansion.starknet.data.types.EstimateFeeResponse -import com.swmansion.starknet.data.types.Felt -import com.swmansion.starknet.data.types.OrderedEvent -import com.swmansion.starknet.data.types.OrderedMessageL2ToL1 -import com.swmansion.starknet.data.types.StateDiff import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/SimulatedTransactionList.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/SimulatedTransactionList.kt new file mode 100644 index 000000000..ef34129fc --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/SimulatedTransactionList.kt @@ -0,0 +1,8 @@ +package com.swmansion.starknet.data.types + +import com.swmansion.starknet.data.serializers.SimulatedTransactionListSerializer +import kotlinx.serialization.Serializable + +@JvmInline +@Serializable(with = SimulatedTransactionListSerializer::class) +value class SimulatedTransactionList(val values: List) : StarknetResponse diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/StarknetChainId.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/StarknetChainId.kt index 27bdeea8b..401025fc6 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/StarknetChainId.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/StarknetChainId.kt @@ -4,7 +4,7 @@ import com.swmansion.starknet.data.serializers.StarknetChainIdSerializer import kotlinx.serialization.Serializable @Serializable(with = StarknetChainIdSerializer::class) -data class StarknetChainId(val value: Felt) { +data class StarknetChainId(val value: Felt) : StarknetResponse { companion object { @field:JvmField val MAIN = StarknetChainId(Felt.fromHex("0x534e5f4d41494e")) // encodeShortString('SN_MAIN'), diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/StarknetResponse.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/StarknetResponse.kt new file mode 100644 index 000000000..dd98e5cbe --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/StarknetResponse.kt @@ -0,0 +1,6 @@ +package com.swmansion.starknet.data.types + +import kotlinx.serialization.Serializable + +@Serializable +sealed interface StarknetResponse diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/StringResponse.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/StringResponse.kt new file mode 100644 index 000000000..87f403cdf --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/StringResponse.kt @@ -0,0 +1,8 @@ +package com.swmansion.starknet.data.types + +import com.swmansion.starknet.data.serializers.StringResponseSerializer +import kotlinx.serialization.Serializable + +@JvmInline +@Serializable(with = StringResponseSerializer::class) +value class StringResponse(val value: String) : StarknetResponse diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/Transaction.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Transaction.kt similarity index 99% rename from lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/Transaction.kt rename to lib/src/main/kotlin/com/swmansion/starknet/data/types/Transaction.kt index c6c25fff3..13464cb87 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/Transaction.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/Transaction.kt @@ -1,8 +1,7 @@ -package com.swmansion.starknet.data.types.transactions +package com.swmansion.starknet.data.types import com.swmansion.starknet.data.Cairo1ClassHashCalculator import com.swmansion.starknet.data.TransactionHashCalculator -import com.swmansion.starknet.data.types.* import com.swmansion.starknet.provider.Provider import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.SerialName @@ -73,7 +72,7 @@ enum class DAMode(val value: Int) { } @Serializable -sealed class Transaction { +sealed class Transaction : StarknetResponse { abstract val hash: Felt? abstract val version: TransactionVersion abstract val signature: Signature diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/TransactionPayload.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/TransactionPayload.kt similarity index 98% rename from lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/TransactionPayload.kt rename to lib/src/main/kotlin/com/swmansion/starknet/data/types/TransactionPayload.kt index 4d0373a99..81bf87f07 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/TransactionPayload.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/TransactionPayload.kt @@ -1,7 +1,6 @@ -package com.swmansion.starknet.data.types.transactions +package com.swmansion.starknet.data.types import com.swmansion.starknet.data.serializers.TransactionPayloadSerializer -import com.swmansion.starknet.data.types.* import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/TransactionReceipt.kt b/lib/src/main/kotlin/com/swmansion/starknet/data/types/TransactionReceipt.kt similarity index 98% rename from lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/TransactionReceipt.kt rename to lib/src/main/kotlin/com/swmansion/starknet/data/types/TransactionReceipt.kt index 675597ba0..806fc9363 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/data/types/transactions/TransactionReceipt.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/data/types/TransactionReceipt.kt @@ -1,6 +1,5 @@ -package com.swmansion.starknet.data.types.transactions +package com.swmansion.starknet.data.types -import com.swmansion.starknet.data.types.* import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -60,7 +59,7 @@ enum class TransactionFinalityStatus { } @Serializable -sealed class TransactionReceipt { +sealed class TransactionReceipt : StarknetResponse { abstract val hash: Felt abstract val type: TransactionType abstract val actualFee: FeePayment diff --git a/lib/src/main/kotlin/com/swmansion/starknet/deployercontract/StandardDeployer.kt b/lib/src/main/kotlin/com/swmansion/starknet/deployercontract/StandardDeployer.kt index ab50826fd..73bd9c06d 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/deployercontract/StandardDeployer.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/deployercontract/StandardDeployer.kt @@ -3,7 +3,6 @@ package com.swmansion.starknet.deployercontract import com.swmansion.starknet.account.Account import com.swmansion.starknet.data.selectorFromName import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* import com.swmansion.starknet.extensions.map import com.swmansion.starknet.extensions.toFelt import com.swmansion.starknet.provider.Provider diff --git a/lib/src/main/kotlin/com/swmansion/starknet/provider/Provider.kt b/lib/src/main/kotlin/com/swmansion/starknet/provider/Provider.kt index c519a96ad..e25191ad9 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/provider/Provider.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/provider/Provider.kt @@ -1,7 +1,6 @@ package com.swmansion.starknet.provider import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* import com.swmansion.starknet.provider.exceptions.RequestFailedException /** @@ -83,7 +82,7 @@ interface Provider { * * @throws RequestFailedException */ - fun getBlockNumber(): Request + fun getBlockNumber(): Request /** * Get the hash and number of the block. @@ -102,7 +101,7 @@ interface Provider { * @param blockTag The tag of the block. * @throws RequestFailedException */ - fun getBlockTransactionCount(blockTag: BlockTag): Request + fun getBlockTransactionCount(blockTag: BlockTag): Request /** * Get the block transaction count. @@ -112,7 +111,7 @@ interface Provider { * @param blockHash The hash of the block. * @throws RequestFailedException */ - fun getBlockTransactionCount(blockHash: Felt): Request + fun getBlockTransactionCount(blockHash: Felt): Request /** * Get the block transaction count. @@ -122,7 +121,7 @@ interface Provider { * @param blockNumber The number of the block. * @throws RequestFailedException */ - fun getBlockTransactionCount(blockNumber: Int): Request + fun getBlockTransactionCount(blockNumber: Int): Request /** * Deploy an account contract using version 1 transaction. @@ -154,7 +153,7 @@ interface Provider { * * @throws RequestFailedException */ - fun callContract(call: Call, blockTag: BlockTag): Request> + fun callContract(call: Call, blockTag: BlockTag): Request /** * Get the version of the spec. @@ -164,7 +163,7 @@ interface Provider { * @throws RequestFailedException * */ - fun getSpecVersion(): Request + fun getSpecVersion(): Request /** * Calls a contract deployed on Starknet. @@ -174,7 +173,7 @@ interface Provider { * * @throws RequestFailedException */ - fun callContract(call: Call, blockHash: Felt): Request> + fun callContract(call: Call, blockHash: Felt): Request /** * Calls a contract deployed on Starknet. @@ -184,7 +183,7 @@ interface Provider { * * @throws RequestFailedException */ - fun callContract(call: Call, blockNumber: Int): Request> + fun callContract(call: Call, blockNumber: Int): Request /** * Calls a contract deployed on Starknet. @@ -195,7 +194,7 @@ interface Provider { * * @throws RequestFailedException */ - fun callContract(call: Call): Request> + fun callContract(call: Call): Request /** * Get a value of storage var. @@ -421,7 +420,7 @@ interface Provider { payload: List, blockHash: Felt, simulationFlags: Set, - ): Request> + ): Request /** * Estimate a fee. @@ -433,7 +432,7 @@ interface Provider { * * @throws RequestFailedException */ - fun getEstimateFee(payload: List, blockHash: Felt): Request> + fun getEstimateFee(payload: List, blockHash: Felt): Request /** * Estimate a fee. @@ -450,7 +449,7 @@ interface Provider { payload: List, blockNumber: Int, simulationFlags: Set, - ): Request> + ): Request /** * Estimate a fee. @@ -462,7 +461,7 @@ interface Provider { * * @throws RequestFailedException */ - fun getEstimateFee(payload: List, blockNumber: Int): Request> + fun getEstimateFee(payload: List, blockNumber: Int): Request /** * Estimate a fee. @@ -479,7 +478,7 @@ interface Provider { payload: List, blockTag: BlockTag, simulationFlags: Set, - ): Request> + ): Request /** * Estimate a fee. @@ -491,7 +490,7 @@ interface Provider { * * @throws RequestFailedException */ - fun getEstimateFee(payload: List, blockTag: BlockTag): Request> + fun getEstimateFee(payload: List, blockTag: BlockTag): Request /** * Estimate a fee. @@ -504,7 +503,7 @@ interface Provider { * @throws RequestFailedException */ - fun getEstimateFee(payload: List, simulationFlags: Set): Request> + fun getEstimateFee(payload: List, simulationFlags: Set): Request /** * Estimate a fee. @@ -516,7 +515,7 @@ interface Provider { * @throws RequestFailedException */ - fun getEstimateFee(payload: List): Request> + fun getEstimateFee(payload: List): Request /** * Estimate a message fee. @@ -791,7 +790,7 @@ interface Provider { * @param simulationFlags set of flags to be used for simulation * @return a list of transaction simulations */ - fun simulateTransactions(transactions: List, blockTag: BlockTag, simulationFlags: Set): Request> + fun simulateTransactions(transactions: List, blockTag: BlockTag, simulationFlags: Set): Request /** Simulate executing a list of transactions * @@ -800,7 +799,7 @@ interface Provider { * @param simulationFlags set of flags to be used for simulation * @return a list of transaction simulations */ - fun simulateTransactions(transactions: List, blockNumber: Int, simulationFlags: Set): Request> + fun simulateTransactions(transactions: List, blockNumber: Int, simulationFlags: Set): Request /** Simulate executing a list of transactions * @@ -809,5 +808,5 @@ interface Provider { * @param simulationFlags set of flags to be used for simulation * @return a list of transaction simulations */ - fun simulateTransactions(transactions: List, blockHash: Felt, simulationFlags: Set): Request> + fun simulateTransactions(transactions: List, blockHash: Felt, simulationFlags: Set): Request } diff --git a/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/BuildJsonHttpDeserializer.kt b/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/BuildJsonHttpDeserializer.kt index 3e2f3b247..69af858e9 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/BuildJsonHttpDeserializer.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/BuildJsonHttpDeserializer.kt @@ -1,109 +1,104 @@ package com.swmansion.starknet.provider.rpc -import com.swmansion.starknet.data.serializers.JsonRpcErrorSerializer +import com.swmansion.starknet.data.types.StarknetResponse import com.swmansion.starknet.provider.exceptions.RequestFailedException import com.swmansion.starknet.provider.exceptions.RpcRequestFailedException -import com.swmansion.starknet.service.http.HttpResponseDeserializer +import com.swmansion.starknet.service.http.HttpResponse +import com.swmansion.starknet.service.http.requests.HttpResponseDeserializer import kotlinx.serialization.* import kotlinx.serialization.json.* import java.util.function.Function -@Serializable -private data class JsonRpcResponse( - @SerialName("id") - val id: Int, - - @SerialName("jsonrpc") - val jsonRpc: String, - - @SerialName("result") - val result: T? = null, - - @SerialName("error") - val error: JsonRpcError? = null, -) - -@Serializable(with = JsonRpcErrorSerializer::class) -internal data class JsonRpcError( - @SerialName("code") - val code: Int, - - @SerialName("message") - val message: String, - - @SerialName("data") - val data: String? = null, -) - -private fun extractResult( +private fun getResult( jsonRpcResponse: JsonRpcResponse, fullPayload: String, - payload: String = fullPayload, -): T { + payload: String, +): Result { if (jsonRpcResponse.error != null) { - throw RpcRequestFailedException( - code = jsonRpcResponse.error.code, - message = jsonRpcResponse.error.message, - data = jsonRpcResponse.error.data, - payload = payload, + return Result.failure( + RpcRequestFailedException( + code = jsonRpcResponse.error.code, + message = jsonRpcResponse.error.message, + data = jsonRpcResponse.error.data, + payload = payload, + ), ) } if (jsonRpcResponse.result == null) { - throw RequestFailedException(message = "Response did not contain a result", payload = fullPayload) + return Result.failure( + RequestFailedException( + message = "Response did not contain a result", + payload = fullPayload, + ), + ) + } + return Result.success(jsonRpcResponse.result) +} + +private fun getOrderedRpcResults( + response: HttpResponse, + deserializationStrategies: List>, + deserializationJson: Json, +): List> { + if (!response.isSuccessful) throw RequestFailedException(payload = response.body) + + val jsonResponses = Json.parseToJsonElement(response.body).jsonArray + val orderedResults = MutableList?>(jsonResponses.size) { null } + + jsonResponses.forEach { jsonElement -> + val id = jsonElement.jsonObject["id"]!!.jsonPrimitive.int + val deserializationStrategy = deserializationStrategies[id] + val jsonRpcResponse = deserializationJson.decodeFromJsonElement( + JsonRpcResponse.serializer(deserializationStrategy), + jsonElement, + ) + orderedResults[id] = getResult(jsonRpcResponse, response.body, jsonElement.toString()) } - return jsonRpcResponse.result + + return orderedResults.filterNotNull() } @JvmSynthetic -internal fun buildJsonHttpDeserializer( +internal fun buildJsonHttpDeserializer( deserializationStrategy: KSerializer, deserializationJson: Json, ): HttpResponseDeserializer { return Function { response -> - if (!response.isSuccessful) { - throw RequestFailedException( - payload = response.body, - ) - } + if (!response.isSuccessful) throw RequestFailedException(payload = response.body) + val jsonRpcResponse = deserializationJson.decodeFromString( JsonRpcResponse.serializer(deserializationStrategy), response.body, ) - extractResult(jsonRpcResponse, response.body) - } -} - -internal fun buildJsonBatchHttpDeserializer( - deserializationStrategies: List>, - deserializationJson: Json, -): HttpResponseDeserializer> { - // TODO: In case of batch request, exception should not be thrown. - // Instead, we want to return wrapped responses. - // This enables access to successful results or encountered errors. - - return Function { response -> - if (!response.isSuccessful) { - throw RequestFailedException( + if (jsonRpcResponse.error != null) { + throw RpcRequestFailedException( + code = jsonRpcResponse.error.code, + message = jsonRpcResponse.error.message, + data = jsonRpcResponse.error.data, payload = response.body, ) } - val jsonResponses = Json.parseToJsonElement(response.body).jsonArray - val orderedResults = MutableList(jsonResponses.size) { null } - - jsonResponses.forEach { jsonElement -> - val id = jsonElement.jsonObject["id"]!!.jsonPrimitive.int - val deserializationStrategy = deserializationStrategies[id] - val jsonRpcResponse = deserializationJson.decodeFromJsonElement( - JsonRpcResponse.serializer(deserializationStrategy), - jsonElement, - ) - orderedResults[id] = extractResult(jsonRpcResponse, response.body, jsonElement.toString()) + if (jsonRpcResponse.result == null) { + throw RequestFailedException(message = "Response did not contain a result", payload = response.body) } - - orderedResults.filterNotNull() + jsonRpcResponse.result } } + +internal fun buildJsonHttpBatchDeserializer( + deserializationStrategies: List>, + deserializationJson: Json, +): HttpResponseDeserializer>> = Function { response -> + getOrderedRpcResults(response, deserializationStrategies, deserializationJson) +} + +internal fun buildJsonHttpBatchDeserializerOfDifferentTypes( + deserializationStrategies: List>, + deserializationJson: Json, +): HttpResponseDeserializer>> = Function { response -> + getOrderedRpcResults(response, deserializationStrategies, deserializationJson) +} diff --git a/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/JsonRpcProvider.kt b/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/JsonRpcProvider.kt index bf788a7db..9366e4e9b 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/JsonRpcProvider.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/JsonRpcProvider.kt @@ -6,31 +6,13 @@ import com.swmansion.starknet.data.serializers.SyncPolymorphicSerializer import com.swmansion.starknet.data.serializers.TransactionPolymorphicSerializer import com.swmansion.starknet.data.serializers.TransactionReceiptPolymorphicSerializer import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* import com.swmansion.starknet.provider.Provider import com.swmansion.starknet.service.http.* +import com.swmansion.starknet.service.http.requests.HttpBatchRequest +import com.swmansion.starknet.service.http.requests.HttpRequest import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.builtins.ListSerializer -import kotlinx.serialization.builtins.serializer import kotlinx.serialization.json.* -@Serializable -internal data class JsonRpcRequest( - @SerialName("id") - val id: Int, - - @SerialName("jsonrpc") - val jsonRpc: String, - - @SerialName("method") - val method: String, - - @SerialName("params") - val params: JsonElement, -) - /** * A provider for interacting with Starknet using JSON-RPC. You should reuse it in your application to share the * httpService or provide it with your own httpService. @@ -58,7 +40,7 @@ class JsonRpcProvider( } } - private fun buildRequest( + private fun buildRequest( method: JsonRpcMethod, paramsJson: JsonElement, responseSerializer: KSerializer, @@ -73,7 +55,13 @@ class JsonRpcProvider( return HttpRequest(url, jsonRpcRequest, responseSerializer, deserializationJson, httpService) } - fun batchRequests(requests: List>): BatchHttpRequest { + /** Batch multiple various calls into a single RPC request + * + * @param requests list of requests to be batched together + * + * @return batch request + */ + fun batchRequestsAny(requests: List>): HttpBatchRequest { require(requests.isNotEmpty()) { "Cannot create a batch request from an empty list of requests." } val orderedRequests = requests.mapIndexed { index, request -> @@ -85,44 +73,81 @@ class JsonRpcProvider( ) } val responseSerializers = requests.map { it.serializer } - return BatchHttpRequest(url, orderedRequests, responseSerializers, deserializationJson, httpService) + return HttpBatchRequest.fromRequestsAny(url, orderedRequests, responseSerializers, deserializationJson, httpService) + } + + /** Batch multiple various calls into a single RPC request + * + * @param requests requests to be batched together + * + * @return batch request + */ + fun batchRequestsAny(vararg requests: HttpRequest): HttpBatchRequest { + return batchRequestsAny(requests.toList()) + } + + /** Batch multiple calls into a single RPC request + * + * @param requests list of requests to be batched together + * + * @return batch request + */ + fun batchRequests(requests: List>): HttpBatchRequest { + require(requests.isNotEmpty()) { "Cannot create a batch request from an empty list of requests." } + + val orderedRequests = requests.mapIndexed { index, request -> + JsonRpcRequest( + id = index, + jsonRpc = "2.0", + method = request.jsonRpcRequest.method, + params = request.jsonRpcRequest.params, + ) + } + val responseSerializers = requests.map { it.serializer } + return HttpBatchRequest.fromRequests(url, orderedRequests, responseSerializers, deserializationJson, httpService) } - fun batchRequests(vararg requests: HttpRequest): BatchHttpRequest { + /** Batch multiple calls into a single RPC request + * + * @param requests requests to be batched together + * + * @return batch request + */ + fun batchRequests(vararg requests: HttpRequest): HttpBatchRequest { return batchRequests(requests.toList()) } - override fun getSpecVersion(): HttpRequest { + override fun getSpecVersion(): HttpRequest { val params = Json.encodeToJsonElement(JsonArray(emptyList())) - return buildRequest(JsonRpcMethod.GET_SPEC_VERSION, params, String.serializer()) + return buildRequest(JsonRpcMethod.GET_SPEC_VERSION, params, StringResponseSerializer) } - private fun callContract(payload: CallContractPayload): HttpRequest> { + private fun callContract(payload: CallContractPayload): HttpRequest { val params = Json.encodeToJsonElement(payload) - return buildRequest(JsonRpcMethod.CALL, params, ListSerializer(Felt.serializer())) + return buildRequest(JsonRpcMethod.CALL, params, FeltArraySerializer) } - override fun callContract(call: Call, blockTag: BlockTag): HttpRequest> { + override fun callContract(call: Call, blockTag: BlockTag): HttpRequest { val payload = CallContractPayload(call, BlockId.Tag(blockTag)) return callContract(payload) } - override fun callContract(call: Call, blockHash: Felt): HttpRequest> { + override fun callContract(call: Call, blockHash: Felt): HttpRequest { val payload = CallContractPayload(call, BlockId.Hash(blockHash)) return callContract(payload) } - override fun callContract(call: Call, blockNumber: Int): HttpRequest> { + override fun callContract(call: Call, blockNumber: Int): HttpRequest { val payload = CallContractPayload(call, BlockId.Number(blockNumber)) return callContract(payload) } - override fun callContract(call: Call): HttpRequest> { + override fun callContract(call: Call): HttpRequest { return callContract(call, BlockTag.LATEST) } @@ -321,13 +346,13 @@ class JsonRpcProvider( return buildRequest(JsonRpcMethod.DECLARE, jsonPayload, DeclareResponse.serializer()) } - override fun getBlockNumber(): HttpRequest { + override fun getBlockNumber(): HttpRequest { val params = Json.encodeToJsonElement(JsonArray(emptyList())) return buildRequest( JsonRpcMethod.GET_BLOCK_NUMBER, params, - Int.serializer(), + IntResponseSerializer, ) } @@ -341,29 +366,29 @@ class JsonRpcProvider( ) } - private fun getBlockTransactionCount(payload: GetBlockTransactionCountPayload): HttpRequest { + private fun getBlockTransactionCount(payload: GetBlockTransactionCountPayload): HttpRequest { val params = Json.encodeToJsonElement(payload) return buildRequest( JsonRpcMethod.GET_BLOCK_TRANSACTION_COUNT, params, - Int.serializer(), + IntResponseSerializer, ) } - override fun getBlockTransactionCount(blockTag: BlockTag): HttpRequest { + override fun getBlockTransactionCount(blockTag: BlockTag): HttpRequest { val payload = GetBlockTransactionCountPayload(BlockId.Tag(blockTag)) return getBlockTransactionCount(payload) } - override fun getBlockTransactionCount(blockHash: Felt): HttpRequest { + override fun getBlockTransactionCount(blockHash: Felt): HttpRequest { val payload = GetBlockTransactionCountPayload(BlockId.Hash(blockHash)) return getBlockTransactionCount(payload) } - override fun getBlockTransactionCount(blockNumber: Int): HttpRequest { + override fun getBlockTransactionCount(blockNumber: Int): HttpRequest { val payload = GetBlockTransactionCountPayload(BlockId.Number(blockNumber)) return getBlockTransactionCount(payload) @@ -378,17 +403,17 @@ class JsonRpcProvider( return buildRequest(JsonRpcMethod.GET_EVENTS, jsonPayload, GetEventsResult.serializer()) } - private fun getEstimateFee(payload: EstimateTransactionFeePayload): HttpRequest> { + private fun getEstimateFee(payload: EstimateTransactionFeePayload): HttpRequest { val jsonPayload = jsonWithDefaults.encodeToJsonElement(payload) - return buildRequest(JsonRpcMethod.ESTIMATE_FEE, jsonPayload, ListSerializer(EstimateFeeResponse.serializer())) + return buildRequest(JsonRpcMethod.ESTIMATE_FEE, jsonPayload, EstimateFeeResponseListSerializer) } override fun getEstimateFee( payload: List, blockHash: Felt, simulationFlags: Set, - ): HttpRequest> { + ): HttpRequest { val estimatePayload = EstimateTransactionFeePayload(payload, simulationFlags, BlockId.Hash(blockHash)) return getEstimateFee(estimatePayload) @@ -397,7 +422,7 @@ class JsonRpcProvider( override fun getEstimateFee( payload: List, blockHash: Felt, - ): HttpRequest> { + ): HttpRequest { return getEstimateFee(payload, blockHash, defaultFeeEstimateSimulationFlags) } @@ -405,7 +430,7 @@ class JsonRpcProvider( payload: List, blockNumber: Int, simulationFlags: Set, - ): HttpRequest> { + ): HttpRequest { val estimatePayload = EstimateTransactionFeePayload(payload, simulationFlags, BlockId.Number(blockNumber)) return getEstimateFee(estimatePayload) @@ -414,7 +439,7 @@ class JsonRpcProvider( override fun getEstimateFee( payload: List, blockNumber: Int, - ): HttpRequest> { + ): HttpRequest { return getEstimateFee(payload, blockNumber, defaultFeeEstimateSimulationFlags) } @@ -422,7 +447,7 @@ class JsonRpcProvider( payload: List, blockTag: BlockTag, simulationFlags: Set, - ): HttpRequest> { + ): HttpRequest { val estimatePayload = EstimateTransactionFeePayload(payload, simulationFlags, BlockId.Tag(blockTag)) return getEstimateFee(estimatePayload) @@ -431,15 +456,18 @@ class JsonRpcProvider( override fun getEstimateFee( payload: List, blockTag: BlockTag, - ): HttpRequest> { + ): HttpRequest { return getEstimateFee(payload, blockTag, defaultFeeEstimateSimulationFlags) } - override fun getEstimateFee(payload: List, simulationFlags: Set): HttpRequest> { + override fun getEstimateFee( + payload: List, + simulationFlags: Set, + ): HttpRequest { return getEstimateFee(payload, BlockTag.PENDING, simulationFlags) } - override fun getEstimateFee(payload: List): HttpRequest> { + override fun getEstimateFee(payload: List): HttpRequest { return getEstimateFee(payload, BlockTag.PENDING, defaultFeeEstimateSimulationFlags) } @@ -630,25 +658,37 @@ class JsonRpcProvider( return getTransactionByBlockIdAndIndex(payload) } - private fun simulateTransactions(payload: SimulateTransactionsPayload): HttpRequest> { + private fun simulateTransactions(payload: SimulateTransactionsPayload): HttpRequest { val params = jsonWithDefaults.encodeToJsonElement(payload) - return buildRequest(JsonRpcMethod.SIMULATE_TRANSACTIONS, params, ListSerializer(SimulatedTransaction.serializer())) + return buildRequest(JsonRpcMethod.SIMULATE_TRANSACTIONS, params, SimulatedTransactionListSerializer) } - override fun simulateTransactions(transactions: List, blockTag: BlockTag, simulationFlags: Set): HttpRequest> { + override fun simulateTransactions( + transactions: List, + blockTag: BlockTag, + simulationFlags: Set, + ): HttpRequest { val payload = SimulateTransactionsPayload(transactions, BlockId.Tag(blockTag), simulationFlags) return simulateTransactions(payload) } - override fun simulateTransactions(transactions: List, blockNumber: Int, simulationFlags: Set): HttpRequest> { + override fun simulateTransactions( + transactions: List, + blockNumber: Int, + simulationFlags: Set, + ): HttpRequest { val payload = SimulateTransactionsPayload(transactions, BlockId.Number(blockNumber), simulationFlags) return simulateTransactions(payload) } - override fun simulateTransactions(transactions: List, blockHash: Felt, simulationFlags: Set): HttpRequest> { + override fun simulateTransactions( + transactions: List, + blockHash: Felt, + simulationFlags: Set, + ): HttpRequest { val payload = SimulateTransactionsPayload(transactions, BlockId.Hash(blockHash), simulationFlags) return simulateTransactions(payload) diff --git a/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/JsonRpcRequest.kt b/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/JsonRpcRequest.kt new file mode 100644 index 000000000..d0617a104 --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/JsonRpcRequest.kt @@ -0,0 +1,20 @@ +package com.swmansion.starknet.provider.rpc + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonElement + +@Serializable +data class JsonRpcRequest( + @SerialName("id") + val id: Int, + + @SerialName("jsonrpc") + val jsonRpc: String, + + @SerialName("method") + val method: String, + + @SerialName("params") + val params: JsonElement, +) diff --git a/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/JsonRpcResponse.kt b/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/JsonRpcResponse.kt new file mode 100644 index 000000000..e2a230c5b --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/provider/rpc/JsonRpcResponse.kt @@ -0,0 +1,33 @@ +package com.swmansion.starknet.provider.rpc + +import com.swmansion.starknet.data.serializers.JsonRpcErrorSerializer +import com.swmansion.starknet.data.types.StarknetResponse +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +internal data class JsonRpcResponse( + @SerialName("id") + val id: Int, + + @SerialName("jsonrpc") + val jsonRpc: String, + + @SerialName("result") + val result: T? = null, + + @SerialName("error") + val error: JsonRpcError? = null, +) + +@Serializable(with = JsonRpcErrorSerializer::class) +internal data class JsonRpcError( + @SerialName("code") + val code: Int, + + @SerialName("message") + val message: String, + + @SerialName("data") + val data: String? = null, +) diff --git a/lib/src/main/kotlin/com/swmansion/starknet/service/http/HttpRequest.kt b/lib/src/main/kotlin/com/swmansion/starknet/service/http/HttpRequest.kt index 360241300..e784713e1 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/service/http/HttpRequest.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/service/http/HttpRequest.kt @@ -1,85 +1,23 @@ package com.swmansion.starknet.service.http import com.swmansion.starknet.provider.Request -import com.swmansion.starknet.provider.rpc.JsonRpcRequest -import com.swmansion.starknet.provider.rpc.buildJsonBatchHttpDeserializer -import com.swmansion.starknet.provider.rpc.buildJsonHttpDeserializer -import kotlinx.serialization.KSerializer -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json import java.util.concurrent.CompletableFuture import java.util.function.Function typealias HttpResponseDeserializer = Function -class HttpRequest private constructor( - internal val jsonRpcRequest: JsonRpcRequest, - internal val serializer: KSerializer, - private val payload: Lazy, - private val deserializer: HttpResponseDeserializer, - private val service: HttpService, +class HttpRequest( + val payload: HttpService.Payload, + val deserializer: HttpResponseDeserializer, + val service: HttpService, ) : Request { - internal constructor( - url: String, - jsonRpcRequest: JsonRpcRequest, - serializer: KSerializer, - deserializationJson: Json, - service: HttpService, - ) : this( - jsonRpcRequest = jsonRpcRequest, - serializer = serializer, - payload = lazy { - HttpService.Payload( - url, - "POST", - emptyList(), - Json.encodeToString(jsonRpcRequest), - ) - }, - deserializer = buildJsonHttpDeserializer(serializer, deserializationJson), - service = service, - ) - override fun send(): T { - val response = service.send(payload.value) - return deserializer.apply(response) - } - - override fun sendAsync(): CompletableFuture { - return service.sendAsync(payload.value).thenApplyAsync(deserializer) - } -} - -class BatchHttpRequest private constructor( - private val payload: HttpService.Payload, - private val deserializer: HttpResponseDeserializer>, - private val service: HttpService, -) : Request> { - - internal constructor( - url: String, - jsonRpcRequests: List, - responseDeserializers: List>, - deserializationJson: Json, - service: HttpService, - ) : this( - HttpService.Payload( - url = url, - method = "POST", - params = emptyList(), - body = Json.encodeToString(jsonRpcRequests), - ), - deserializer = buildJsonBatchHttpDeserializer(responseDeserializers, deserializationJson), - service = service, - ) - - override fun send(): List { val response = service.send(payload) return deserializer.apply(response) } - override fun sendAsync(): CompletableFuture> { + override fun sendAsync(): CompletableFuture { return service.sendAsync(payload).thenApplyAsync(deserializer) } } diff --git a/lib/src/main/kotlin/com/swmansion/starknet/service/http/requests/HttpBatchRequest.kt b/lib/src/main/kotlin/com/swmansion/starknet/service/http/requests/HttpBatchRequest.kt new file mode 100644 index 000000000..1555146da --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/service/http/requests/HttpBatchRequest.kt @@ -0,0 +1,69 @@ +package com.swmansion.starknet.service.http.requests + +import com.swmansion.starknet.data.types.StarknetResponse +import com.swmansion.starknet.provider.Request +import com.swmansion.starknet.provider.rpc.JsonRpcRequest +import com.swmansion.starknet.provider.rpc.buildJsonHttpBatchDeserializer +import com.swmansion.starknet.provider.rpc.buildJsonHttpBatchDeserializerOfDifferentTypes +import com.swmansion.starknet.service.http.HttpService +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import java.util.concurrent.CompletableFuture + +class HttpBatchRequest private constructor( + private val payload: HttpService.Payload, + private val deserializer: HttpResponseDeserializer>>, + private val service: HttpService, +) : Request>> { + override fun send(): List> { + val response = service.send(payload) + return deserializer.apply(response) + } + + override fun sendAsync(): CompletableFuture>> { + return service.sendAsync(payload).thenApplyAsync(deserializer) + } + + companion object { + @JvmStatic + fun fromRequests( + url: String, + jsonRpcRequests: List, + responseDeserializers: List>, + deserializationJson: Json, + service: HttpService, + ): HttpBatchRequest { + return HttpBatchRequest( + HttpService.Payload( + url = url, + method = "POST", + params = emptyList(), + body = Json.encodeToString(jsonRpcRequests), + ), + deserializer = buildJsonHttpBatchDeserializer(responseDeserializers, deserializationJson), + service = service, + ) + } + + @JvmStatic + fun fromRequestsAny( + url: String, + jsonRpcRequests: List, + responseDeserializers: List>, + deserializationJson: Json, + service: HttpService, + ): HttpBatchRequest { + return HttpBatchRequest( + HttpService.Payload( + url = url, + method = "POST", + params = emptyList(), + body = Json.encodeToString(jsonRpcRequests), + ), + deserializer = buildJsonHttpBatchDeserializerOfDifferentTypes(responseDeserializers, deserializationJson), + service = service, + ) + } + } +} diff --git a/lib/src/main/kotlin/com/swmansion/starknet/service/http/requests/HttpRequest.kt b/lib/src/main/kotlin/com/swmansion/starknet/service/http/requests/HttpRequest.kt new file mode 100644 index 000000000..729ab3527 --- /dev/null +++ b/lib/src/main/kotlin/com/swmansion/starknet/service/http/requests/HttpRequest.kt @@ -0,0 +1,54 @@ +package com.swmansion.starknet.service.http.requests + +import com.swmansion.starknet.data.types.StarknetResponse +import com.swmansion.starknet.provider.Request +import com.swmansion.starknet.provider.rpc.JsonRpcRequest +import com.swmansion.starknet.provider.rpc.buildJsonHttpDeserializer +import com.swmansion.starknet.service.http.HttpResponse +import com.swmansion.starknet.service.http.HttpService +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import java.util.concurrent.CompletableFuture +import java.util.function.Function + +typealias HttpResponseDeserializer = Function + +class HttpRequest private constructor( + internal val jsonRpcRequest: JsonRpcRequest, + internal val serializer: KSerializer, + private val payload: Lazy, + private val deserializer: HttpResponseDeserializer, + private val service: HttpService, +) : Request { + + internal constructor( + url: String, + jsonRpcRequest: JsonRpcRequest, + serializer: KSerializer, + deserializationJson: Json, + service: HttpService, + ) : this( + jsonRpcRequest = jsonRpcRequest, + serializer = serializer, + payload = lazy { + HttpService.Payload( + url, + "POST", + emptyList(), + Json.encodeToString(jsonRpcRequest), + ) + }, + deserializer = buildJsonHttpDeserializer(serializer, deserializationJson), + service = service, + ) + + override fun send(): T { + val response = service.send(payload.value) + return deserializer.apply(response) + } + + override fun sendAsync(): CompletableFuture { + return service.sendAsync(payload.value).thenApplyAsync(deserializer) + } +} diff --git a/lib/src/main/kotlin/com/swmansion/starknet/signer/Signer.kt b/lib/src/main/kotlin/com/swmansion/starknet/signer/Signer.kt index eb7170f0c..40b573961 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/signer/Signer.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/signer/Signer.kt @@ -2,7 +2,6 @@ package com.swmansion.starknet.signer import com.swmansion.starknet.data.TypedData import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* /** * Transaction signer. diff --git a/lib/src/main/kotlin/com/swmansion/starknet/signer/StarkCurveSigner.kt b/lib/src/main/kotlin/com/swmansion/starknet/signer/StarkCurveSigner.kt index a6c9a0ef4..ce693f192 100644 --- a/lib/src/main/kotlin/com/swmansion/starknet/signer/StarkCurveSigner.kt +++ b/lib/src/main/kotlin/com/swmansion/starknet/signer/StarkCurveSigner.kt @@ -3,7 +3,6 @@ package com.swmansion.starknet.signer import com.swmansion.starknet.crypto.StarknetCurve import com.swmansion.starknet.data.TypedData import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* /** * Signer implementing a stark curve signature (default signature used on Starknet). diff --git a/lib/src/test/kotlin/com/swmansion/starknet/data/TransactionHashCalculatorTest.kt b/lib/src/test/kotlin/com/swmansion/starknet/data/TransactionHashCalculatorTest.kt index 3c00c00da..1ebee6ea3 100644 --- a/lib/src/test/kotlin/com/swmansion/starknet/data/TransactionHashCalculatorTest.kt +++ b/lib/src/test/kotlin/com/swmansion/starknet/data/TransactionHashCalculatorTest.kt @@ -1,8 +1,8 @@ package com.swmansion.starknet.data import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.DAMode -import com.swmansion.starknet.data.types.transactions.TransactionVersion +import com.swmansion.starknet.data.types.DAMode +import com.swmansion.starknet.data.types.TransactionVersion import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test diff --git a/lib/src/test/kotlin/network/account/AccountTest.kt b/lib/src/test/kotlin/network/account/AccountTest.kt index 39ef939e1..73dbd2c91 100644 --- a/lib/src/test/kotlin/network/account/AccountTest.kt +++ b/lib/src/test/kotlin/network/account/AccountTest.kt @@ -4,7 +4,6 @@ import com.swmansion.starknet.account.StandardAccount import com.swmansion.starknet.crypto.StarknetCurve import com.swmansion.starknet.data.ContractAddressCalculator import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* import com.swmansion.starknet.deployercontract.StandardDeployer import com.swmansion.starknet.extensions.toFelt import com.swmansion.starknet.extensions.toUint256 @@ -93,7 +92,7 @@ class AccountTest { listOf(call), skipValidate = false, ) - val estimateFeeResponse = estimateFeeRequest.send().first().overallFee + val estimateFeeResponse = estimateFeeRequest.send().values.first().overallFee assertTrue(estimateFeeResponse.value > Felt.ONE.value) } @@ -136,7 +135,7 @@ class AccountTest { val feeEstimateRequest = provider.getEstimateFee(listOf(signedTransaction.toPayload()), BlockTag.LATEST, emptySet()) - val feeEstimate = feeEstimateRequest.send().first() + val feeEstimate = feeEstimateRequest.send().values.first() assertNotEquals(Felt(0), feeEstimate.gasConsumed) assertNotEquals(Felt(0), feeEstimate.gasPrice) assertNotEquals(Felt(0), feeEstimate.overallFee) @@ -172,7 +171,7 @@ class AccountTest { val feeEstimateRequest = provider.getEstimateFee(listOf(declareTransactionPayload), BlockTag.PENDING) - val feeEstimate = feeEstimateRequest.send().first() + val feeEstimate = feeEstimateRequest.send().values.first() assertNotEquals(Felt(0), feeEstimate.gasConsumed) assertNotEquals(Felt(0), feeEstimate.gasPrice) assertNotEquals(Felt(0), feeEstimate.overallFee) @@ -391,7 +390,7 @@ class AccountTest { assertEquals(TransactionVersion.V1_QUERY, payloadForFeeEstimation.version) val feePayload = provider.getEstimateFee(listOf(payloadForFeeEstimation)).send() - assertTrue(feePayload.first().overallFee.value > Felt.ONE.value) + assertTrue(feePayload.values.first().overallFee.value > Felt.ONE.value) } @Test @@ -551,7 +550,7 @@ class AccountTest { ) val feeEstimateRequest = provider.getEstimateFee(listOf(payloadForFeeEstimate)) - val feeEstimate = feeEstimateRequest.send().first() + val feeEstimate = feeEstimateRequest.send().values.first() val resourceBounds = feeEstimate.toResourceBounds() val call = Call( @@ -646,12 +645,12 @@ class AccountTest { blockTag = BlockTag.LATEST, simulationFlags = simulationFlags, ).send() - assertEquals(2, simulationResult.size) - assertTrue(simulationResult[0].transactionTrace is InvokeTransactionTraceBase) - assertTrue(simulationResult[0].transactionTrace is InvokeTransactionTrace) - assertTrue(simulationResult[1].transactionTrace is InvokeTransactionTraceBase) - assertTrue(simulationResult[1].transactionTrace is RevertedInvokeTransactionTrace) - assertNotNull((simulationResult[1].transactionTrace as RevertedInvokeTransactionTrace).executeInvocation.revertReason) + assertEquals(2, simulationResult.values.size) + assertTrue(simulationResult.values[0].transactionTrace is InvokeTransactionTraceBase) + assertTrue(simulationResult.values[0].transactionTrace is InvokeTransactionTrace) + assertTrue(simulationResult.values[1].transactionTrace is InvokeTransactionTraceBase) + assertTrue(simulationResult.values[1].transactionTrace is RevertedInvokeTransactionTrace) + assertNotNull((simulationResult.values[1].transactionTrace as RevertedInvokeTransactionTrace).executeInvocation.revertReason) val invokeTxWithoutSignature = InvokeTransactionV1Payload(invokeTx.senderAddress, invokeTx.calldata, emptyList(), invokeTx.maxFee, invokeTx.version, invokeTx.nonce) val invokeTxWihtoutSignature2 = InvokeTransactionV1Payload(invokeTx2.senderAddress, invokeTx2.calldata, emptyList(), invokeTx2.maxFee, invokeTx2.version, invokeTx2.nonce) @@ -662,12 +661,12 @@ class AccountTest { simulationFlags = simulationFlags2, ).send() - assertEquals(2, simulationResult2.size) - assertTrue(simulationResult[0].transactionTrace is InvokeTransactionTraceBase) - assertTrue(simulationResult[0].transactionTrace is InvokeTransactionTrace) - assertTrue(simulationResult[1].transactionTrace is InvokeTransactionTraceBase) - assertTrue(simulationResult[1].transactionTrace is RevertedInvokeTransactionTrace) - assertNotNull((simulationResult[1].transactionTrace as RevertedInvokeTransactionTrace).executeInvocation.revertReason) + assertEquals(2, simulationResult2.values.size) + assertTrue(simulationResult.values[0].transactionTrace is InvokeTransactionTraceBase) + assertTrue(simulationResult.values[0].transactionTrace is InvokeTransactionTrace) + assertTrue(simulationResult.values[1].transactionTrace is InvokeTransactionTraceBase) + assertTrue(simulationResult.values[1].transactionTrace is RevertedInvokeTransactionTrace) + assertNotNull((simulationResult.values[1].transactionTrace as RevertedInvokeTransactionTrace).executeInvocation.revertReason) } @Test @@ -698,8 +697,8 @@ class AccountTest { blockTag = BlockTag.LATEST, simulationFlags = simulationFlags, ).send() - assertEquals(1, simulationResult.size) - assertTrue(simulationResult[0].transactionTrace is DeployAccountTransactionTrace) + assertEquals(1, simulationResult.values.size) + assertTrue(simulationResult.values[0].transactionTrace is DeployAccountTransactionTrace) val deployAccountTxWithoutSignature = DeployAccountTransactionV1Payload(deployAccountTx.classHash, deployAccountTx.salt, deployAccountTx.constructorCalldata, deployAccountTx.version, deployAccountTx.nonce, deployAccountTx.maxFee, emptyList()) @@ -710,8 +709,8 @@ class AccountTest { simulationFlags = simulationFlags2, ).send() - assertEquals(1, simulationResult2.size) - assertTrue(simulationResult[0].transactionTrace is DeployAccountTransactionTrace) + assertEquals(1, simulationResult2.values.size) + assertTrue(simulationResult.values[0].transactionTrace is DeployAccountTransactionTrace) } @Test @@ -747,8 +746,8 @@ class AccountTest { blockTag = BlockTag.LATEST, simulationFlags = simulationFlags, ).send() - assertEquals(1, simulationResult.size) - val trace = simulationResult.first().transactionTrace + assertEquals(1, simulationResult.values.size) + val trace = simulationResult.values.first().transactionTrace assertTrue(trace is DeclareTransactionTrace) } diff --git a/lib/src/test/kotlin/network/provider/ProviderTest.kt b/lib/src/test/kotlin/network/provider/ProviderTest.kt index 5582ec453..ab5cb9d54 100644 --- a/lib/src/test/kotlin/network/provider/ProviderTest.kt +++ b/lib/src/test/kotlin/network/provider/ProviderTest.kt @@ -1,7 +1,6 @@ package network.provider import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* import com.swmansion.starknet.provider.rpc.JsonRpcProvider import network.utils.NetworkConfig import network.utils.NetworkConfig.Network @@ -77,7 +76,7 @@ class ProviderTest { assumeTrue(NetworkConfig.isTestEnabled(requiresGas = false)) val request = provider.getSpecVersion() - val specVersion = request.send() + val specVersion = request.send().value assertNotEquals(0, specVersion.length) val validPattern = "\\d+\\.\\d+\\.\\d+".toRegex() diff --git a/lib/src/test/kotlin/starknet/account/StandardAccountTest.kt b/lib/src/test/kotlin/starknet/account/StandardAccountTest.kt index 071118bd4..b12ac67bf 100644 --- a/lib/src/test/kotlin/starknet/account/StandardAccountTest.kt +++ b/lib/src/test/kotlin/starknet/account/StandardAccountTest.kt @@ -6,7 +6,6 @@ import com.swmansion.starknet.crypto.StarknetCurve import com.swmansion.starknet.data.ContractAddressCalculator import com.swmansion.starknet.data.selectorFromName import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* import com.swmansion.starknet.extensions.toFelt import com.swmansion.starknet.provider.exceptions.RequestFailedException import com.swmansion.starknet.provider.rpc.JsonRpcProvider @@ -111,7 +110,7 @@ class StandardAccountTest { @Test fun `get nonce at block number`() { - val blockNumber = provider.getBlockNumber().send() + val blockNumber = provider.getBlockNumber().send().value val nonce = account.getNonce(blockNumber).send() assert(nonce >= Felt.ZERO) @@ -139,7 +138,7 @@ class StandardAccountTest { val call = Call(balanceContractAddress, "increase_balance", listOf(Felt(10))) val request = account.estimateFeeV1(call) - val feeEstimate = request.send().first() + val feeEstimate = request.send().values.first() assertNotEquals(Felt.ZERO, feeEstimate.overallFee) assertEquals( @@ -156,7 +155,7 @@ class StandardAccountTest { listOf(call), skipValidate = false, ) - val feeEstimate = request.send().first() + val feeEstimate = request.send().values.first() assertNotEquals(Felt.ZERO, feeEstimate.overallFee) assertEquals( @@ -192,7 +191,7 @@ class StandardAccountTest { ) val feeEstimates = request.send() - feeEstimates.forEach { + feeEstimates.values.forEach { assertNotEquals(Felt.ZERO, it.overallFee) assertEquals( it.gasPrice.value * it.gasConsumed.value + it.dataGasPrice.value * it.dataGasConsumed.value, @@ -206,7 +205,7 @@ class StandardAccountTest { val call = Call(balanceContractAddress, "increase_balance", listOf(Felt(10))) val request = account.estimateFeeV1(call, BlockTag.LATEST) - val feeEstimate = request.send().first() + val feeEstimate = request.send().values.first() assertNotEquals(Felt.ZERO, feeEstimate.overallFee) assertEquals( @@ -237,7 +236,7 @@ class StandardAccountTest { assertEquals(TransactionVersion.V2_QUERY, declareTransactionPayload.version) val request = provider.getEstimateFee(payload = listOf(declareTransactionPayload), simulationFlags = emptySet()) - val feeEstimate = request.send().first() + val feeEstimate = request.send().values.first() assertNotEquals(Felt.ZERO, feeEstimate.overallFee) assertEquals( @@ -266,7 +265,7 @@ class StandardAccountTest { assertEquals(TransactionVersion.V3_QUERY, declareTransactionPayload.version) val request = provider.getEstimateFee(payload = listOf(declareTransactionPayload), simulationFlags = emptySet()) - val feeEstimate = request.send().first() + val feeEstimate = request.send().values.first() assertNotEquals(Felt.ZERO, feeEstimate.overallFee) assertEquals( @@ -850,7 +849,7 @@ class StandardAccountTest { assertEquals(TransactionVersion.V1_QUERY, payloadForFeeEstimation.version) val feePayload = provider.getEstimateFee(listOf(payloadForFeeEstimation)).send() - assertTrue(feePayload.first().overallFee.value > Felt.ONE.value) + assertTrue(feePayload.values.first().overallFee.value > Felt.ONE.value) } @Test @@ -886,7 +885,7 @@ class StandardAccountTest { assertEquals(TransactionVersion.V3_QUERY, payloadForFeeEstimation.version) val feePayload = provider.getEstimateFee(listOf(payloadForFeeEstimation)).send() - assertTrue(feePayload.first().overallFee.value > Felt.ONE.value) + assertTrue(feePayload.values.first().overallFee.value > Felt.ONE.value) } } @@ -1088,10 +1087,10 @@ class StandardAccountTest { blockTag = BlockTag.PENDING, simulationFlags = simulationFlags, ).send() - assertEquals(2, simulationResult.size) - assertTrue(simulationResult[0].transactionTrace is InvokeTransactionTraceBase) - assertTrue(simulationResult[0].transactionTrace is InvokeTransactionTrace) - assertTrue(simulationResult[1].transactionTrace is DeployAccountTransactionTrace) + assertEquals(2, simulationResult.values.size) + assertTrue(simulationResult.values[0].transactionTrace is InvokeTransactionTraceBase) + assertTrue(simulationResult.values[0].transactionTrace is InvokeTransactionTrace) + assertTrue(simulationResult.values[1].transactionTrace is DeployAccountTransactionTrace) val invokeTxWithoutSignature = invokeTx.copy(signature = emptyList()) val deployAccountTxWithoutSignature = deployAccountTx.copy(signature = emptyList()) @@ -1103,10 +1102,10 @@ class StandardAccountTest { simulationFlags = simulationFlags2, ).send() - assertEquals(2, simulationResult2.size) - assertTrue(simulationResult[0].transactionTrace is InvokeTransactionTraceBase) - assertTrue(simulationResult[0].transactionTrace is InvokeTransactionTrace) - assertTrue(simulationResult[1].transactionTrace is DeployAccountTransactionTrace) + assertEquals(2, simulationResult2.values.size) + assertTrue(simulationResult.values[0].transactionTrace is InvokeTransactionTraceBase) + assertTrue(simulationResult.values[0].transactionTrace is InvokeTransactionTrace) + assertTrue(simulationResult.values[1].transactionTrace is DeployAccountTransactionTrace) } @Test @@ -1155,10 +1154,10 @@ class StandardAccountTest { blockTag = BlockTag.PENDING, simulationFlags = simulationFlags, ).send() - assertEquals(2, simulationResult.size) - assertTrue(simulationResult[0].transactionTrace is InvokeTransactionTraceBase) - assertTrue(simulationResult[0].transactionTrace is InvokeTransactionTrace) - assertTrue(simulationResult[1].transactionTrace is DeployAccountTransactionTrace) + assertEquals(2, simulationResult.values.size) + assertTrue(simulationResult.values[0].transactionTrace is InvokeTransactionTraceBase) + assertTrue(simulationResult.values[0].transactionTrace is InvokeTransactionTrace) + assertTrue(simulationResult.values[1].transactionTrace is DeployAccountTransactionTrace) } @Test @@ -1195,8 +1194,8 @@ class StandardAccountTest { blockTag = BlockTag.PENDING, simulationFlags = simulationFlags, ).send() - assertEquals(1, simulationResult.size) - val trace = simulationResult.first().transactionTrace + assertEquals(1, simulationResult.values.size) + val trace = simulationResult.values.first().transactionTrace assertTrue(trace is DeclareTransactionTrace) } @@ -1237,8 +1236,8 @@ class StandardAccountTest { blockTag = BlockTag.PENDING, simulationFlags = simulationFlags, ).send() - assertEquals(1, simulationResult.size) - val trace = simulationResult.first().transactionTrace + assertEquals(1, simulationResult.values.size) + val trace = simulationResult.values.first().transactionTrace assertTrue(trace is DeclareTransactionTrace) } @@ -1294,7 +1293,7 @@ class StandardAccountTest { simulationFlags = simulationFlags, ).send() - val trace = simulationResult.first().transactionTrace + val trace = simulationResult.values.first().transactionTrace assertTrue(trace is InvokeTransactionTraceBase) assertTrue(trace is RevertedInvokeTransactionTrace) val revertedTrace = trace as RevertedInvokeTransactionTrace @@ -1418,7 +1417,7 @@ class StandardAccountTest { simulationFlags = simulationFlags, ).send() - val trace = simulationResult.first().transactionTrace + val trace = simulationResult.values.first().transactionTrace assertTrue(trace is InvokeTransactionTrace) val invokeTrace = trace as InvokeTransactionTrace val messages = invokeTrace.executeInvocation.messages diff --git a/lib/src/test/kotlin/starknet/data/TransactionStatusMappingTest.kt b/lib/src/test/kotlin/starknet/data/TransactionStatusMappingTest.kt index 9dd74b226..39dc9d3de 100644 --- a/lib/src/test/kotlin/starknet/data/TransactionStatusMappingTest.kt +++ b/lib/src/test/kotlin/starknet/data/TransactionStatusMappingTest.kt @@ -1,6 +1,6 @@ package starknet.data -import com.swmansion.starknet.data.types.transactions.TransactionStatus +import com.swmansion.starknet.data.types.TransactionStatus import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json import org.junit.jupiter.api.Assertions.assertEquals diff --git a/lib/src/test/kotlin/starknet/data/types/TransactionsTest.kt b/lib/src/test/kotlin/starknet/data/types/TransactionsTest.kt index 2cad1c39e..2a8791f10 100644 --- a/lib/src/test/kotlin/starknet/data/types/TransactionsTest.kt +++ b/lib/src/test/kotlin/starknet/data/types/TransactionsTest.kt @@ -2,7 +2,6 @@ package starknet.data.types import com.swmansion.starknet.data.serializers.BlockIdSerializer import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json diff --git a/lib/src/test/kotlin/starknet/provider/ProviderTest.kt b/lib/src/test/kotlin/starknet/provider/ProviderTest.kt index 5ca37144a..835207c40 100644 --- a/lib/src/test/kotlin/starknet/provider/ProviderTest.kt +++ b/lib/src/test/kotlin/starknet/provider/ProviderTest.kt @@ -2,7 +2,6 @@ package starknet.provider import com.swmansion.starknet.data.selectorFromName import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.* import com.swmansion.starknet.provider.exceptions.RequestFailedException import com.swmansion.starknet.provider.exceptions.RpcRequestFailedException import com.swmansion.starknet.provider.rpc.JsonRpcProvider @@ -68,7 +67,7 @@ class ProviderTest { @Test fun `get spec version`() { val request = provider.getSpecVersion() - val specVersion = request.send() + val specVersion = request.send().value assertNotEquals(0, specVersion.length) val validPattern = "\\d+\\.\\d+\\.\\d+".toRegex() @@ -87,7 +86,7 @@ class ProviderTest { @Test fun `call contract with block number`() { - val currentNumber = provider.getBlockNumber().send() + val currentNumber = provider.getBlockNumber().send().value val call = Call( contractAddress = balanceContractAddress, @@ -182,7 +181,7 @@ class ProviderTest { @Test fun `get class definition at class hash (block number)`() { - val blockNumber = provider.getBlockNumber().send() + val blockNumber = provider.getBlockNumber().send().value val request = provider.getClass(balanceClassHash, blockNumber) val response = request.send() @@ -224,7 +223,7 @@ class ProviderTest { @Test fun `get class definition at contract address (block number)`() { - val blockNumber = provider.getBlockNumber().send() + val blockNumber = provider.getBlockNumber().send().value val request = provider.getClassAt(balanceContractAddress, blockNumber) val response = request.send() @@ -287,7 +286,7 @@ class ProviderTest { @Test fun `get class hash at block number`() { - val blockNumber = provider.getBlockNumber().send() + val blockNumber = provider.getBlockNumber().send().value val request = provider.getClassHashAt(balanceContractAddress, blockNumber) val response = request.send() @@ -784,7 +783,7 @@ class ProviderTest { @Test fun `get nonce with block number`() { - val blockNumber = provider.getBlockNumber().send() + val blockNumber = provider.getBlockNumber().send().value val request = provider.getNonce(balanceContractAddress, blockNumber) val response = request.send() @@ -884,7 +883,7 @@ class ProviderTest { @Test fun `get block with transactions with block number`() { - val blockNumber = provider.getBlockNumber().send() + val blockNumber = provider.getBlockNumber().send().value val request = provider.getBlockWithTxs(blockNumber) val response = request.send() @@ -1031,7 +1030,7 @@ class ProviderTest { @Test fun `get block with transaction receipts with block number`() { - val blockNumber = provider.getBlockNumber().send() + val blockNumber = provider.getBlockNumber().send().value val request = provider.getBlockWithReceipts(blockNumber) val response = request.send() @@ -1102,7 +1101,7 @@ class ProviderTest { @Test fun `get block with transaction hashes with block number`() { - val blockNumber = provider.getBlockNumber().send() + val blockNumber = provider.getBlockNumber().send().value val request = provider.getBlockWithTxHashes(blockNumber) val response = request.send() @@ -1161,7 +1160,7 @@ class ProviderTest { @Test fun `get state of block with number`() { - val blockNumber = provider.getBlockNumber().send() + val blockNumber = provider.getBlockNumber().send().value val request = provider.getStateUpdate(blockNumber) val response = request.send() @@ -1190,7 +1189,7 @@ class ProviderTest { @Test fun `get transactions by block number and index`() { - val blockNumber = provider.getBlockNumber().send() + val blockNumber = provider.getBlockNumber().send().value val request = provider.getTransactionByBlockIdAndIndex(blockNumber, 0) val response = request.send() @@ -1227,25 +1226,48 @@ class ProviderTest { val response = request.send() val expectedBalance = provider.getStorageAt(balanceContractAddress, selectorFromName("balance"), BlockTag.LATEST).send() - assertEquals(response[0].first(), expectedBalance) - assertEquals(response[1].first(), expectedBalance) + assertEquals(response[0].getOrThrow().first(), expectedBalance) + assertEquals(response[1].getOrThrow().first(), expectedBalance) } @Test fun `batch get transactions`() { - val blockNumber = provider.getBlockNumber().send() + val blockNumber = provider.getBlockNumber().send().value val request = provider.batchRequests( provider.getTransactionByBlockIdAndIndex(blockNumber, 0), provider.getTransaction(invokeTransactionHash), provider.getTransaction(declareTransactionHash), provider.getTransaction(deployAccountTransactionHash), + ) val response = request.send() - assertEquals(response[0].hash, invokeTransactionHash) - assertEquals(response[1].hash, invokeTransactionHash) - assertEquals(response[2].hash, declareTransactionHash) - assertEquals(response[3].hash, deployAccountTransactionHash) + assertEquals(response[0].getOrThrow().hash, invokeTransactionHash) + assertEquals(response[1].getOrThrow().hash, invokeTransactionHash) + assertEquals(response[2].getOrThrow().hash, declareTransactionHash) + assertEquals(response[3].getOrThrow().hash, deployAccountTransactionHash) + } + + @Test + fun `batch requests any`() { + val request = provider.batchRequestsAny( + provider.getTransaction(invokeTransactionHash), + provider.getBlockNumber(), + provider.getTransactionStatus(invokeTransactionHash), + ) + + val response = request.send() + + val transaction = response[0].getOrThrow() as Transaction + val blockNumber = (response[1].getOrThrow() as IntResponse).value + val txStatus = response[2].getOrThrow() as GetTransactionStatusResponse + + assertEquals(transaction.hash, invokeTransactionHash) + + assertNotEquals(0, blockNumber) + + assertEquals(TransactionStatus.ACCEPTED_ON_L2, txStatus.finalityStatus) + assertEquals(TransactionExecutionStatus.SUCCEEDED, txStatus.executionStatus) } } diff --git a/lib/src/test/kotlin/starknet/provider/response/JsonRpcResponseTest.kt b/lib/src/test/kotlin/starknet/provider/response/JsonRpcResponseTest.kt index a165b1144..a0451e899 100644 --- a/lib/src/test/kotlin/starknet/provider/response/JsonRpcResponseTest.kt +++ b/lib/src/test/kotlin/starknet/provider/response/JsonRpcResponseTest.kt @@ -1,8 +1,6 @@ package starknet.provider.response import com.swmansion.starknet.data.types.* -import com.swmansion.starknet.data.types.transactions.TransactionExecutionStatus -import com.swmansion.starknet.data.types.transactions.TransactionStatus import com.swmansion.starknet.provider.exceptions.RequestFailedException import com.swmansion.starknet.provider.exceptions.RpcRequestFailedException import com.swmansion.starknet.provider.rpc.JsonRpcProvider @@ -195,26 +193,68 @@ class JsonRpcResponseTest { val mockResponse = """ [ { + "id": "1", "jsonrpc": "2.0", "result": { "finality_status": "ACCEPTED_ON_L2", "execution_status": "REVERTED" - }, - "id": "1" + } }, { + "id": "0", "jsonrpc": "2.0", "result": { "finality_status": "ACCEPTED_ON_L2", "execution_status": "SUCCEEDED" - }, - "id": "0" + } } ] """.trimIndent() - val txHash1 = "0x06376162aed112c9ded4fad481d514decdc0cb766c765b892e368e11891eff8d" - val txHash2 = "0x04a092caa24beca481307c1d7e4bc2fa0156e495701c4e0250367eea23352bc5" + val httpServiceMock = mock { + on { send(any()) } doReturn HttpResponse(true, 200, mockResponse) + } + val provider = JsonRpcProvider("", httpServiceMock) + + val request = provider.batchRequests( + provider.getTransactionStatus(Felt(1)), + provider.getTransactionStatus(Felt(2)), + ) + val response = request.send() + + val txStatusResponse1 = response[0].getOrThrow() + val txStatusResponse2 = response[1].getOrThrow() + + assertEquals(txStatusResponse1.finalityStatus, TransactionStatus.ACCEPTED_ON_L2) + assertEquals(txStatusResponse1.executionStatus, TransactionExecutionStatus.SUCCEEDED) + + assertEquals(txStatusResponse2.finalityStatus, TransactionStatus.ACCEPTED_ON_L2) + assertEquals(txStatusResponse2.executionStatus, TransactionExecutionStatus.REVERTED) + } + + @Test + fun `rpc provider parses batch response with error`() { + val mockResponse = """ + [ + { + "id": "1", + "jsonrpc": "2.0", + "result": { + "finality_status": "ACCEPTED_ON_L2", + "execution_status": "REVERTED" + } + }, + { + "id": 0, + "jsonrpc": "2.0", + "error": { + "code": -32603, + "message": "Internal error", + "data": "Invalid message selector" + } + } + ] + """.trimIndent() val httpServiceMock = mock { on { send(any()) } doReturn HttpResponse(true, 200, mockResponse) @@ -222,15 +262,17 @@ class JsonRpcResponseTest { val provider = JsonRpcProvider("", httpServiceMock) val request = provider.batchRequests( - provider.getTransactionStatus(Felt.fromHex(txHash1)), - provider.getTransactionStatus(Felt.fromHex(txHash2)), + provider.getTransactionStatus(Felt(1)), + provider.getTransactionStatus(Felt(1)), ) val response = request.send() - assertEquals(response[0].finalityStatus, TransactionStatus.ACCEPTED_ON_L2) - assertEquals(response[0].executionStatus, TransactionExecutionStatus.SUCCEEDED) + val txStatusResponse1 = response[0] + val txStatusResponse2 = response[1] + + assertThrows { txStatusResponse1.getOrThrow() } - assertEquals(response[1].finalityStatus, TransactionStatus.ACCEPTED_ON_L2) - assertEquals(response[1].executionStatus, TransactionExecutionStatus.REVERTED) + assertEquals(txStatusResponse2.getOrThrow().finalityStatus, TransactionStatus.ACCEPTED_ON_L2) + assertEquals(txStatusResponse2.getOrThrow().executionStatus, TransactionExecutionStatus.REVERTED) } } diff --git a/lib/src/test/kotlin/starknet/utils/DevnetClient.kt b/lib/src/test/kotlin/starknet/utils/DevnetClient.kt index c6bfeb7ad..daedac7d0 100644 --- a/lib/src/test/kotlin/starknet/utils/DevnetClient.kt +++ b/lib/src/test/kotlin/starknet/utils/DevnetClient.kt @@ -2,8 +2,8 @@ package starknet.utils import com.swmansion.starknet.data.types.Felt import com.swmansion.starknet.data.types.PriceUnit -import com.swmansion.starknet.data.types.transactions.TransactionExecutionStatus -import com.swmansion.starknet.data.types.transactions.TransactionStatus +import com.swmansion.starknet.data.types.TransactionExecutionStatus +import com.swmansion.starknet.data.types.TransactionStatus import com.swmansion.starknet.provider.Provider import com.swmansion.starknet.provider.rpc.JsonRpcProvider import com.swmansion.starknet.service.http.HttpService diff --git a/lib/starknet-jvm.md b/lib/starknet-jvm.md index bc9ec5bdc..00a3667f8 100644 --- a/lib/starknet-jvm.md +++ b/lib/starknet-jvm.md @@ -494,16 +494,93 @@ fun main(args: Array) { // Access output values from batch the response val balance1 = Uint256( - low = batchResponse[0][0], - high = batchResponse[0][1], + low = batchResponse[0].getOrThrow()[0], + high = batchResponse[0].getOrThrow()[1], ) val balance2 = Uint256( - low = batchResponse[1][0], - high = batchResponse[1][1], + low = batchResponse[1].getOrThrow()[0], + high = batchResponse[1].getOrThrow()[1], ) } ``` +## Making multiple calls of different types in one request + +### In Java + +```java +import com.swmansion.starknet.data.types.transactions.Transaction; +import com.swmansion.starknet.data.types.*; +import com.swmansion.starknet.provider.Request; +import com.swmansion.starknet.provider.rpc.JsonRpcProvider; + +import java.util.List; + +public class Main { + public static void main(String[] args) { + // Create a provider for interacting with Starknet + JsonRpcProvider provider = new JsonRpcProvider("https://example-node-url.com/rpc"); + + // Create requests + Request txRequest1 = provider.getTransaction(Felt.fromHex("0x0123")); + Request txRequest2 = provider.getTransaction(Felt.fromHex("0x0456")); + Request txStatusRequest = provider.getTransactionStatus(Felt.fromHex("0x0789")); + Request blockWithTxHashesRequest = provider.getBlockWithTxHashes(Felt.fromHex("0x0abc")); + + // Create a batch request of different types and send it + List response = provider.batchRequestsAny( + txRequest1, + txRequest2, + txStatusRequest, + blockWithTxHashesRequest + ).send(); + + // Access output values from the response + Transaction tx1 = (Transaction) response.get(0); + Transaction tx2 = (Transaction) response.get(1); + GetTransactionStatusResponse txStatus = (GetTransactionStatusResponse) response.get(2); + BlockWithTransactionHashes blockWithTxHashes = (BlockWithTransactionHashes) response.get(3); + } +} +``` + +### In Kotlin + +```kotlin +import com.swmansion.starknet.data.types.BlockWithTransactionHashes +import com.swmansion.starknet.data.types.Felt +import com.swmansion.starknet.data.types.GetTransactionStatusResponse +import com.swmansion.starknet.data.types.Transaction +import com.swmansion.starknet.provider.rpc.JsonRpcProvider + +fun main(args: Array) { + // Create a provider for interacting with Starknet + val provider = JsonRpcProvider("https://example-node-url.com/rpc") + + // Create requests + val txRequest1 = provider.getTransaction(Felt.fromHex("0x0123")) + val txRequest2 = provider.getTransaction(Felt.fromHex("0x0456")) + val txStatusRequest = provider.getTransactionStatus(Felt.fromHex("0x0789")) + val blockWithTxHashesRequest = provider.getBlockWithTxHashes(Felt.fromHex("0x0abc")) + + val batchRequest = provider.batchRequestsAny( + txRequest1, + txRequest2, + txStatusRequest, + blockWithTxHashesRequest + ) + + // Send the batch request + val response = batchRequest.send() + + // Access output values from the response + val tx1 = response[0].getOrThrow() as Transaction + val tx2 = response[1].getOrThrow() as Transaction + val txStatus = response[2].getOrThrow() as GetTransactionStatusResponse + val blockWithTxHashes = response[3].getOrThrow() as BlockWithTransactionHashes +} +``` + ## Declaring Cairo 1/2 contract ### In Java