Skip to content

Commit

Permalink
Support RPC 0.7.0 (#409)
Browse files Browse the repository at this point in the history
  • Loading branch information
DelevoXDG authored Mar 5, 2024
1 parent 9a6e40a commit 819434c
Show file tree
Hide file tree
Showing 24 changed files with 1,166 additions and 598 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

runs-on: ${{ matrix.os }}
env:
DEVNET_SHA: 55191ee549b33ccbb0bc9d20dd929e39832a5ea5
DEVNET_SHA: c6ffb99597eeea58d1a6a30fc061de69e586c779
steps:
- uses: actions/checkout@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion lib/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import org.jetbrains.dokka.gradle.DokkaTask

version = "0.10.1"
version = "0.11.0"
group = "com.swmansion.starknet"

plugins {
Expand Down
54 changes: 54 additions & 0 deletions lib/src/main/kotlin/com/swmansion/starknet/account/Account.kt
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,60 @@ interface Account {
*/
fun executeV3(call: Call, l1ResourceBounds: ResourceBounds): Request<InvokeFunctionResponse>

/**
* Execute a list of calls using version 1 invoke transaction with automatically estimated fee
* that will be multiplied by the specified multiplier when max fee is calculated.
*
* @see [EstimateFeeResponse.toMaxFee] for algorithm used to calculate max fee.
*
* @param calls a list of calls to be executed.
* @param estimateFeeMultiplier how big multiplier should be used for the estimated fee.
*
* @return Invoke function response, containing transaction hash.
*/
fun executeV1(calls: List<Call>, estimateFeeMultiplier: Double): Request<InvokeFunctionResponse>

/**
* Execute a list of calls using version 3 invoke transaction with automatically estimated fee
* that will be multiplied by the specified multipliers when resource bounds are calculated.
*
* @see [EstimateFeeResponse.toResourceBounds] for algorithm used to calculate resource bounds.
*
* @param calls a list of calls to be executed.
* @param estimateAmountMultiplier how big multiplier should be used for the estimated amount.
* @param estimateUnitPriceMultiplier how big multiplier should be used for the estimated unit price.
*
* @return Invoke function response, containing transaction hash.
*/
fun executeV3(calls: List<Call>, estimateAmountMultiplier: Double, estimateUnitPriceMultiplier: Double): Request<InvokeFunctionResponse>

/**
* Execute single call using version 1 invoke transaction with automatically estimated fee
* that will be multiplied by the specified multiplier when max fee is calculated.
*
* @see [EstimateFeeResponse.toMaxFee] for algorithm used to calculate max fee.
*
* @param call a call to be executed.
* @param estimateFeeMultiplier how big multiplier should be used for the estimated fee.
*
* @return Invoke function response, containing transaction hash.
*/
fun executeV1(call: Call, estimateFeeMultiplier: Double): Request<InvokeFunctionResponse>

/**
* Execute single call using version 3 invoke transaction with automatically estimated fee
* that will be multiplied by the specified multipliers when resource bounds are calculated.
*
* @see [EstimateFeeResponse.toResourceBounds] for algorithm used to calculate resource bounds.
*
* @param call a call to be executed.
* @param estimateAmountMultiplier how big multiplier should be used for the estimated amount.
* @param estimateUnitPriceMultiplier how big multiplier should be used for the estimated unit price.
*
* @return Invoke function response, containing transaction hash.
*/
fun executeV3(call: Call, estimateAmountMultiplier: Double, estimateUnitPriceMultiplier: Double): Request<InvokeFunctionResponse>

/**
* Execute a list of calls with automatically estimated fee using version 1 invoke transaction.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,27 @@ class StandardAccount @JvmOverloads constructor(
}
}

override fun executeV1(calls: List<Call>, estimateFeeMultiplier: Double): Request<InvokeFunctionResponse> {
return estimateFeeV1(calls).compose { estimateFee ->
val maxFee = estimateFee.first().toMaxFee(estimateFeeMultiplier)
executeV1(calls, maxFee)
}
}

override fun executeV3(
calls: List<Call>,
estimateAmountMultiplier: Double,
estimateUnitPriceMultiplier: Double,
): Request<InvokeFunctionResponse> {
return estimateFeeV3(calls).compose { estimateFee ->
val resourceBounds = estimateFee.first().toResourceBounds(
amountMultiplier = estimateAmountMultiplier,
unitPriceMultiplier = estimateUnitPriceMultiplier,
)
executeV3(calls, resourceBounds.l1Gas)
}
}

override fun executeV1(calls: List<Call>): Request<InvokeFunctionResponse> {
return estimateFeeV1(calls).compose { estimateFee ->
val maxFee = estimateFee.first().toMaxFee()
Expand All @@ -282,6 +303,22 @@ class StandardAccount @JvmOverloads constructor(
return executeV3(listOf(call), l1ResourceBounds)
}

override fun executeV1(call: Call, estimateFeeMultiplier: Double): Request<InvokeFunctionResponse> {
return executeV1(listOf(call), estimateFeeMultiplier)
}

override fun executeV3(
call: Call,
estimateAmountMultiplier: Double,
estimateUnitPriceMultiplier: Double,
): Request<InvokeFunctionResponse> {
return executeV3(
calls = listOf(call),
estimateAmountMultiplier = estimateAmountMultiplier,
estimateUnitPriceMultiplier = estimateUnitPriceMultiplier,
)
}

override fun executeV1(call: Call): Request<InvokeFunctionResponse> {
return executeV1(listOf(call))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
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
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonContentPolymorphicSerializer
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject

internal object BlockWithTransactionsPolymorphicSerializer : JsonContentPolymorphicSerializer<BlockWithTransactions>(BlockWithTransactions::class) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<BlockWithTransactions> {
return when (isPendingBlock(element.jsonObject)) {
true -> PendingBlockWithTransactions.serializer()
false -> ProcessedBlockWithTransactions.serializer()
}
}
}

internal object BlockWithTransactionHashesPolymorphicSerializer : JsonContentPolymorphicSerializer<BlockWithTransactionHashes>(BlockWithTransactionHashes::class) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<BlockWithTransactionHashes> {
return when (isPendingBlock(element.jsonObject)) {
true -> PendingBlockWithTransactionHashes.serializer()
false -> ProcessedBlockWithTransactionHashes.serializer()
}
}
}

internal object BlockWithReceiptsPolymorphicSerializer : JsonContentPolymorphicSerializer<BlockWithReceipts>(BlockWithReceipts::class) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<BlockWithReceipts> {
return when (isPendingBlock(element.jsonObject)) {
true -> PendingBlockWithReceipts.serializer()
false -> ProcessedBlockWithReceiptsSerializer
}
}
}

internal object ProcessedBlockWithReceiptsSerializer : KSerializer<ProcessedBlockWithReceipts> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ProcessedBlockWithReceipts", PrimitiveKind.STRING)

override fun serialize(encoder: Encoder, value: ProcessedBlockWithReceipts) {
ProcessedBlockWithReceipts.serializer().serialize(encoder, value)
}

override fun deserialize(decoder: Decoder): ProcessedBlockWithReceipts {
val block = ProcessedBlockWithReceipts.serializer().deserialize(decoder)

val transactionsWithReceipts = block.transactionsWithReceipts.map { transactionWithReceipt ->
val updatedReceipt = when (val receipt = transactionWithReceipt.receipt) {
is InvokeTransactionReceipt -> receipt.copy(blockHash = block.blockHash, blockNumber = block.blockNumber)
is DeclareTransactionReceipt -> receipt.copy(blockHash = block.blockHash, blockNumber = block.blockNumber)
is DeployAccountTransactionReceipt -> receipt.copy(blockHash = block.blockHash, blockNumber = block.blockNumber)
is DeployTransactionReceipt -> receipt.copy(blockHash = block.blockHash, blockNumber = block.blockNumber)
is L1HandlerTransactionReceipt -> receipt.copy(blockHash = block.blockHash, blockNumber = block.blockNumber)
}
transactionWithReceipt.copy(receipt = updatedReceipt)
}

return block.copy(transactionsWithReceipts = transactionsWithReceipts)
}
}

private fun isPendingBlock(element: JsonObject): Boolean {
return listOf("block_hash", "block_number", "new_root").any { it !in element }
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,13 @@ internal object TransactionReceiptPolymorphicSerializer :
val typeElement = jsonElement.getOrElse("type") { throw SerializationException("Input element does not contain mandatory field 'type'") }

val type = Json.decodeFromJsonElement(TransactionType.serializer(), typeElement)
val isPending = listOf("block_hash", "block_number").any { it !in jsonElement }

return when (type) {
TransactionType.INVOKE -> when (isPending) {
false -> ProcessedInvokeTransactionReceipt.serializer()
true -> PendingInvokeTransactionReceipt.serializer()
}
TransactionType.DECLARE -> when (isPending) {
false -> ProcessedDeclareTransactionReceipt.serializer()
true -> PendingDeclareTransactionReceipt.serializer()
}
TransactionType.DEPLOY_ACCOUNT -> when (isPending) {
false -> ProcessedDeployAccountTransactionReceipt.serializer()
true -> PendingDeployAccountTransactionReceipt.serializer()
}
TransactionType.DEPLOY -> ProcessedDeployTransactionReceipt.serializer()
TransactionType.L1_HANDLER -> when (isPending) {
false -> ProcessedL1HandlerTransactionReceipt.serializer()
true -> PendingL1HandlerTransactionReceipt.serializer()
}
TransactionType.INVOKE -> InvokeTransactionReceipt.serializer()
TransactionType.DEPLOY_ACCOUNT -> DeployAccountTransactionReceipt.serializer()
TransactionType.DECLARE -> DeclareTransactionReceipt.serializer()
TransactionType.L1_HANDLER -> L1HandlerTransactionReceipt.serializer()
TransactionType.DEPLOY -> DeployTransactionReceipt.serializer()
}
}
}
Loading

0 comments on commit 819434c

Please sign in to comment.